home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Textfiles / cracking / CrackingGuide.txt < prev    next >
Text File  |  1998-08-07  |  289KB  |  4,531 lines

  1.  
  2. ================================================================================
  3. ====== Mac Cracking- A series on deprotection methods on the Macintosh =======
  4.  
  5. Part 1
  6.  
  7. Here it is. First in the series of the Infamous Atom's mac crack series. Some of you may have macs,
  8. others just wonder how you crack on the mac. In this series I'll attempt to show you the basics of
  9. cracking on a mac and hopefully give you an idea of the difficultly and difference between Apple ][
  10. and Mac cracking.
  11.  
  12. 1) Things that make Mac cracking easier than Apple ][:
  13.  
  14. A) All code segments must be stored on the disk in normal format. No abnormal headers or anything
  15. that cannot be read with the normal ROM read routine.(data can be stored otherwise though)
  16. B) Protection on the mac has used fairly simple techniques since the programmers don't know all the
  17. tricks that they do on the II
  18. C) All disk I/O has to pass through the IWM chip and thus you can't have half and spiral tracking.
  19.  
  20. 2) Things that make Mac cracking harder than Apple ][:
  21.  
  22. A) No debugger(or monitor) in ROM.. Macsbug is a software debugger only and therefore can be
  23. destroyed by some nasty programs(EA does it on all of theirs)
  24. B) Programs have much more memory to play with. Instead of 0-$C000, you have $0-$400000 (of course
  25. most of the top is ROM.)
  26. C) Virtually no documentation on non-standard read routines. Basically have to figure it out
  27. yourself.
  28.  
  29. The first thing you need to do before attempting a crack on the Mac is learn 68000 assembly (duuhä)
  30. WELL!! don't just look at it and assume you know it!! You must really understand the addressing modes
  31. and especially how the stack is handled. EVERYTHING on the Mac uses the stack. The code you are
  32. following is constantly calculating addresses and placing them on the stack to RTS to. Also, pick up
  33. a copy of Inside Mac so you can get a basic Idea of the ROM traps (there are over 300).
  34.  
  35. If you want to look for books, I suggest 68000 assembly by Leventhal and the Inside Mac phonebook or
  36. vol.1-3 from Apple.
  37.  
  38. Next time, I'll start showing you some traps, and a little 68000, then we'll jump right in to the
  39. debugger and cracking a ware- Wizardry!
  40.  
  41. ====== Mac Cracking- A series on deprotection methods on the Macintosh =======
  42.  
  43. Welcome to part 2 of The Atom's guide to Mac cracking-
  44.  
  45. Today's Topic- 68000 assembly and Mac Traps
  46.  
  47. By now, I assume you have looked at the 68000 assembly language somewhat and can at least understand
  48. small sections of code. Just to clarify things, and teach you some machine-dependent ideas (for the
  49. mac that is), I'll devote this part of the cracking series to the 68000 and traps/interrupts.
  50.  
  51. First of all, the 68000 is a two instruction machine, unlike the 6502. This means that most commands
  52. have 2 arguments rather than one (as the 6502 has). IE> MOVE D0,#$1000 instead of STA #$1000. This
  53. makes life much easier, especially with the use of multiple registers. (68000 has 17, compared to the
  54. 4 on the 6502). These registers are labelled D0-7, A0-7, and the processor status reg. The registers
  55. starting with D are data registers which are 32 bits long. You can store any kind of 32 bit number in
  56. them. The address registers, (denoted by A), are also 32 bits long but can only refer to even
  57. numbered addresses and are not valid for all modes. (Don't worry if it doesn't make much sense,
  58. you'll get the hang of it.)
  59.  
  60. Soooä Now we know about registers. How about operands? Unlike the 6502, which has a different command
  61. for each register, the 68000 has a standard set of commands which can work with all the regs.
  62. Instead of: STA $1000 or STY $1000,
  63. You would have: MOVE D0,$1000 or MOVE D1,$1000
  64. The MOVE command is the basic operand to move  data from one place to another. Be it from reg to reg
  65. (MOVE D0,D1) or memory to memory (MOVE $1000,$2000), or whatever.
  66.  
  67. Most of the other commands are similar to 6502, and work pretty much the same (JSR, RTS, CMP, BEQ,
  68. BNE, etc.). There is one other addition to the syntax you should know: the .B, .W, and .L suffixes.
  69. These refer to byte, word, and long data commands. By adding any of these to the end of an operand,
  70. you limit the command to only that size of data. For instance, a MOVE.B D0,D1 would move the lowest 8
  71. bits of D0 into the first 8 bits of D1. The word command uses 16 bits, and long word uses all 32.
  72. These can be added to most commands that manipulate data, like CMP, CLR, MOV, ROL, etc. If you ignore
  73. the syntax, it defaults to .W.
  74.  
  75. Now we get to Addressing modes: On the 6502, you had different syntax for addressing, and its about
  76. the same on the 68000. An indirect jump (JMP ($1000)) would become JMP ($1000)ä really hard huh? You
  77. can use inderict addressing in MOVE commands also: MOVE (A0),D1. This would move the contents of
  78. whatever address was in A0 into D1. (IF $1000 was in A0, then the word at $1000 would go to D1). One
  79. note, the indirect mode can only be used with the address registers, not the data registers.
  80.  
  81. Finally, there are the auto-increment and auto-decrement indirect modes. If you did a MOVE (A0)+,D1
  82. (and A0 was $1000), it would the contents of $1000 into D1, and then automatically increment A0 so it
  83. now points to $1002. (It increments by 2 since it moved a word (2 bytes) and each address points to a
  84. byte (in effect, its now pointing to the next WORD)). Auto-decrement works basically the same way, a
  85. MOVE -(A0),D1, would decrement the address in A0 by 2, then move the contents of $FFE into D1. The
  86. placement of the - or + is the way its set up, so you can't do a MOVE +(A0),D1 or MOV (A0)-,D1.
  87.  
  88. And a couple more sytnax things- there are no stack commands (PHA,etc.), they use the auto-inc and
  89. auto-dec modes to implement a stack with the A7 register. It's kind of complicated exactly how it
  90. works, so I won't go into it here, but just assume that MOVE D0,-(A7) pushes D0 onto the stack and
  91. MOVE (A7)+,D0 pops the value off the stack into D0. (the A7 is sometimes replaced by SP as in MOVE
  92. D0,-(SP)).
  93.  
  94. So now we know everything there is to know about 68000 assembly, right?
  95. Wrongä but we know enough to crack something!
  96.  
  97.  
  98. But before I start talking about the debugger, I'll mention something about the traps on the 68000.
  99. Since all ROM routines are called through these, it pays to know what they are.
  100.  
  101. First of all, when the 68000 finds an opcode it doesnt know (some code that doesn't translate into an
  102. executable instruction), it will look in a trap table to see if there is a replacement code for it.
  103. This way, you can implement your own 68000 commands by putting the address of your routine into the
  104. trap table and simply issuing the command. On the Mac, the trap tables are in low memory and point to
  105. ROM routines. Since the routines are always in the same place with the same ROMs, the debugger keeps
  106. a table of these traps and will actually name them for you in the code. So while listing a section of
  107. memory, you may see something like this:
  108.  
  109. _InitGraf
  110. _InitFonts
  111. _InitWindows
  112. MOVE    #14,D0
  113. MOVE    D0,-(SP)
  114.  _Read
  115.  
  116. What it is doing is calling three rom routines to initialize different sections of the window
  117. management, executing a couple of 68000 instructions and then calling the Read ROM routine to read
  118. from the disk. Fairly simple, right? It does make cracking quite a bit easier, as long as you know
  119. what most of the traps do. So be sure and have a copy of Inside Mac at hand when you start to
  120. debug/crack something.(and lots of paper).
  121.  
  122. Well, next time, we'll look at the debugger and start trying to crack a few warezä
  123.  
  124. ====== Mac Cracking- A series on deprotection methods on the Macintosh =======
  125.  
  126. Part 3 
  127.  
  128. Here we are again, with the 3rd installment of "Mac Cracking- man or myth?"
  129. (or something like that).
  130.  
  131. The topic of discussion in this section will be the DEBUGGER. Otherwise known as MacsBug. If you end
  132. up doing much cracking at all, you'll begin to love (and hate) some of MacsBug's commands, and you
  133. should get fairly familiar with reading other people's 68000 code.(or compiler code).
  134.  
  135. First, a couple notes about MacsBug: To run it, you must have the MacsBug file on the disk you are
  136. booting up, and it must be named MacsBug exactly, (well, case doesnt matter, but otherwise, exactly
  137. like that). If you are using the HFS system, it must be in the system folder along with the system
  138. and finder files. Also, don't forget to install the little  programmer's switch in the side of your
  139. mac. If you don't have it in, you can't even start up MacsBug!
  140.  
  141. Ok, well, I'll start by talking about how MacsBug is loaded in, set up, and then list some commands
  142. and show you some examples.
  143.  
  144. Booting up-
  145. When the mac boots up, it reads a bunch of system related stuff from the boot disk, initializes the
  146. Font, QuickDraw, Resource and other managers, and then throws up a Dialog saying "Welcome to
  147. Macintosh". It then looks for a file name MacsBug on the disk, and if it finds it, it allocates some
  148. extra memory for it and then loads it in and sets it all up. Macsbug takes up about 40k, so for large
  149. programs, running on a 128k, you may not be able to load it.(get a 512k!)
  150.  
  151. Basically what MacsBug does when it sets up is change a few pointers in low RAM that used to point to
  152. error routines to point to it. Like the error when you hit the interrupt button on the side of the
  153. computer (plus a few more). So now, when you hit the interrupt button, instead of getting a bomb
  154. dialog, a new window will pop up, covering most of the screen, with a dump of all the registers
  155. (D0-D7 and A0-A7 as well as the PC and some other info). You are now in MacsBug! You have stolen
  156. control of the 68000 from the executing program and can now debug (or crack) to your hearts content
  157. but first, you need to know the MacsBug commands!
  158.  
  159. Commands
  160.  
  161. MacsBug has a lot of commands. At least 40. It basically works the same as the monitor on a II, but
  162. with different syntax, and a bunch of nice tracing functions. They are set up in a general format of
  163. a one or two word command, followed by a few numeric parameters.
  164.  
  165. What follows is a partial list of the basic commands we will be using to crack Wizardry, and some
  166. explanation for each. To get a list of all the commands, look in your Inside Mac manual under the
  167. section called "INSIDE MACSBUG" (only in newer versions).
  168.  
  169. Oh yea, forgot to mention, I'm using MacsBug V5.1. These commands work with all versions 5.0 and
  170. higher. (You can check your version of MacsBug by typing DV <cr> at the prompt.)
  171.  
  172. (aaaa = address, nnnn = number)
  173.  
  174. Memory Commands:
  175.  
  176. DM aaaa nnnn Display memory- gives you hex dump of the bytes starting at aaaa and going up to address
  177. aaaa+nnnn. Ex. DM 0F00 10 would dump out hex from $F00 to $F10. If you leave out the nnnn, it lists
  178. the next 16 bytes. If you leave out aaaa, it starts at the current address.
  179.  
  180. SM aaaa nn,nn1,nn2ä Set memory- changes value in address aaaa to nn, then address aaaa+1 to nn1, etc.
  181.  
  182. TD Total Display- dumps out all the registers, PC and disassembles the current line.
  183.  
  184. Break Commands:
  185.  
  186. BR aaaa Sets a break point at address aaaa. When the program executes the line at aaaa, it will be
  187. interrupted and the MacsBug window will pop up.
  188.  
  189. G aaaa Just like the Apple ][, starts execution at aaaa. If you leave off aaaa, it starts where the
  190. PC last was.
  191.  
  192. GT aaaa Very nice command, starts executing at the PC, and then stops and returns to MacsBug when it
  193. gets to address aaaa (easier than setting breakpoints).
  194.  
  195. T Trace, executes one instruction, then dumps out the registers and disassembles the next line.
  196.  
  197. MR Magic Return. If you are tracing along, and suddenly encounter a JSR, you can type MR and it will
  198. execute the subroutine and then return you to trace mode right after it gets a RTS.
  199.  
  200. A Trap Commands:
  201.  
  202. (these are probably the most important, be sure you understand them)
  203.  
  204. AB TRAPNAME Causes the computer to halt and return to MacsBug when it sees a TRAP command that is
  205. referred to by TRAPNAME. Ex. AB READ would stop the next time the program does a READ call.
  206.  
  207. AT TRAPNAME Traces and displays the address of each call to the trap TRAPNAME. Doesnt halt though.
  208. Ex. AT EJECT would show the address of each line that the program executed that called the EJECT
  209. trap, and then continue executing the program.
  210.  
  211. AX Clear all trap commands. (so it won't stop everytime it does a READ anymore)
  212.  
  213. Disassembler commands:
  214.  
  215. IL aaaa nnnn List out disassembled code starting at address aaaa and going until address aaaa+nnnn.
  216. Just like the L command on the ][. If you just enter IL <CR> it will list out the next 10 or so
  217. instructions.
  218.  
  219. So those are all the commands you need to know! there are a bunch more, but they aren't as powerful
  220. or as easy to understand as these, so you can learn them on your own.
  221.  
  222. Just to give you and example of using the debugger, I'll show the steps you might use to find the
  223. starting address of a program:
  224.  
  225. 1) put MacsBug on the disk with the program you are trying to find the starting address for. (Well,
  226. call it PROGRAM.)
  227. 2) Boot up the disk, and go to the desktop.
  228. 3) Press the interrupt button- you should see a big window pop up with a dump of the registers in it.
  229. 4) Type AB INITGRAF This tells MacsBug to stop the next time it encounters an _InitGraf call.
  230. (_InitGraf is usually one of the first instructions applications run, so it will close to the
  231. starting address.)
  232. 5) Hit G to start the finder running again.
  233. 6) Double click on PROGRAM and hope for the best!
  234. 7) If all goes ok, MacsBug should pop up in a little while, displaying the address of the instruction
  235. that called _InitGraf.
  236. 8) Type IL aaaa, where aaaa is the address that MacsBug said the _InitGraf instruction was at.
  237. 9) Thats it! the beginning of the code for our application! from there, we could trace on using the T
  238. command and watch the execution of the program. Or hit G to give the program back full control of the
  239. 68000.
  240.  
  241. Don't forget to do an AX command when you are done, otherwise you will be jumping into macsbug
  242. everytime you run an application that calls _InitGraf.
  243.  
  244. Finally, I'd like to say something about MacsBug alternatives: I know of one great debugger called
  245. MCBUG. it works a lot like MacsBug, but has a few extra features that help a lot, like a built in
  246. mini-assembler, some nice launch funtions, and a few other helpful commands. It's a shareware/public
  247. domain program, so if you look around you should be able to find a copy of it on CompuServe or from a
  248. user group. It comes with docs, and installs just like MacsBug; simply rename it and boot!
  249.  
  250. ====== Mac Cracking- A series on deprotection methods on the Macintosh =======
  251.  
  252. Welcome to Part 4 of Mac Cracking- your guide to fame.
  253.  
  254. In this, the fourth, and hopefully final part, we will look at Wizardry and actually remove its
  255. protection. Of course, as we all know, this is only for backup purposes, right?
  256.  
  257. So first we need to set up a copy of the disk to work on. Wizardry is an unusual protection, in that
  258. you can copy all the files off the disk, but it asks you to put the master disk back in upon boot,
  259. and then reads some bad blocks off of the master disk. The nice thing about this method is that it
  260. does not crash the machine if it can't find the master, it simply continues with a semi-demo game of
  261. Wiz. This saves a lot of time when you are constantly backtracking and reloading the files to find
  262. the protection.
  263.  
  264. Here we go!
  265.  
  266. First, sector copy (or finder copy) the files from the Wizardry disk onto a blank. Then trash the
  267. Imagewriter file (we need more space for MacsBug). Copy MacsBug onto the Wizardry disk, and then
  268. select the Wizardry file, and install a MiniFinder with only Wizardry in the selection. This way,
  269. when the disk boots up, we can set up some breakpoints while the MiniFinder is running, and then
  270. execute Wizardry. If we let it boot straight into Wizardry, we would have to guess when to hit the
  271. interrupt switch and hope that we didn't miss something.
  272.  
  273. Now we have a disk to crack. Boot up the disk, and when you see the MiniFinder, hit the interrupt
  274. switch. MacsBug should come up. Type AB INITGRAF <cr>. This will find the starting address of the
  275. program by halting when it starts initializing the managers. Now type G. You are back in the
  276. MiniFinder, so double click on the Wizardry file and wait for MacsBug to regain control.
  277.  
  278. At this point, MacsBug should appear saying it halted on an _InitGraf call at location F200 (this
  279. address will be different depending on your memory size. F200 is on a 512 or plus). You can now type
  280. IL F200 to start listing the code. As we look at the code (hit return to see another 20 lines after
  281. you are done with a section) we see that the program contains no branching until address F222. The
  282. protection check is going to involve reading a sector from the disk and then branching on a result.
  283. So all we have to look for is a branch after some disk access.
  284.  
  285. Type GT F222. Wizardry loads in some resources and sets up its menus and windows. If you booted up
  286. your copy of wizardry normally, this is right before it puts up a dialog and asks for the key disk.
  287. Now we have to narrow down the search to a specific JSR. If you try GT F322, you see that it goes
  288. through the check and comes back with a message that you did not insert the master disk. This means
  289. that the JSR to the protection routine is somewhere between F222 and F322. So now we look some more!
  290.  
  291. (If you did try the GT F322, you can type EA to exit to the application, re-running Wizardry. It will
  292. abort again at the _InitGraf, and then you can type GT F222 to get back to where you belong.)
  293.  
  294. By continuing this process (trying locations closer and closer to F222 in the GT command) you will
  295. eventually find that the JSR to the protection is at F31E. The program does not throw up a dialog
  296. saying you inserted the wrong disk before this JSR, but does draw a dialog at F322, the next
  297. statement. So we have tracked it down to a single JSR. Now we can have fun.
  298.  
  299. If we trace, using the T command at this subroutine, we find that it immediately executes a _LoadSeg
  300. trap. And then for some mysterious reason, MacsBug never regains control. This is the tricky part-
  301. After the JSR to EFB7A (the _LoadSeg), the program loads the protection routine from disk AND loads
  302. code into EFB7A. Since the T command replaces the code at the next instruction with a break command
  303. in order to regain control after one step, this code is loaded on top of the break command, replacing
  304. it. This is why your MacsBug never comes back. There is not a break point to interrupt the program
  305. any more!
  306.  
  307. What we can do though, is interrupt with the interrupt switch after it brings up a dialog saying we
  308. inserted the wrong disk, and disassemble the code that was loaded into EFB7A. When we look there, we
  309. see it did a JMP to 13828. The code at 13828 was also loaded in with this loadseg trap, so we didnt
  310. see it before. This is the main protection routine.
  311.  
  312. But now we have a problem- how do we stop the execution of the program at 13828 so we can trace the
  313. protection and find the correct branch? We can't set a breakpoint at 13828 with GT, since it would
  314. get replaced with the code during the _LoadSeg. And we can't stop it after the _LoadSeg since it
  315. replaces itself and any breakpoints we set after it! What do we do?? Alas, MacsBug comes through with
  316. yet another amazing command. ST. This works like the GT, but does not set a breakpoint to stop the
  317. program. (I'm not sure what it does to do this, but it uses the 68000 step flag.)
  318.  
  319. So we get back to F31E (using the EA command as before, then the GT). And type ST 13828. The reason
  320. we don't issue a ST right after F200 is that the S commands slows execution of the program
  321. noticeably. You will have to wait a couple of minutes for the ST 13828 to return to MacsBug. (The
  322. drive will make some strange noises, but don't worry, just be patient.)
  323.  
  324. After this hard work, we are now in trace mode at 13828. Hurrah! Almost there. By repeating the
  325. method we used to find the first JSR, and by reading the code, you find that the last branch that
  326. seperates a key disk dialog from the bad disk dialog is at 139D0. The BEQ +90 is executed if the
  327. protection check comes out bad. If you search the code, you see that the good code continues 3
  328. instructions from the address the BEQ branches to. So now we simply replace the BEQ with BRA +98, and
  329. no matter what the protection check returns, everything continues fine.
  330.  
  331. Now to test it to be sure our patch works. Boot the disk from scratch and get to
  332. the trace mode at 13828 using the commands we used before. Now type SM 139D0 60 00 00 98. This is the
  333. code for a BRA +98, which we are replacing at 139D0. Hit G, and there it is! Your copy should
  334. continue to load, and no matter what disk you put in for the master, it will thank you for inserting
  335. your "master" and continue along its merry way.
  336.  
  337. But we don't want to have to use MacsBug to do this EVERY time we boot up, so we'll change the
  338. program on the disk. First, dump the memory from the instructions before and after the BEQ +90 and
  339. write them down. Then run Fedit (its a sector editor program) and open the file Wizardry on your
  340. cracking disk. Do a hex search for the values- 0A 00 00 01 67 00 00 90 30 2E FF F2 (These are the
  341. bytes surrounding the instruction that you wrote down earlier. By searching for the whole string, we
  342. are sure we have the correct BEQ +92 in the program, in case there is more than one). Go in to hex
  343. edit mode and replace the 67 00 00 90 with 60 00 00 98 and write thesector back out.
  344.  
  345. Congratulations, you have successfully cracked Wizardry. You can copy the Wizardry file you patched
  346. onto your master disk, or make the patch to a sector copy of the original to get the disk back
  347. looking like it normally did. (Auto boot into Wizardry, no MacsBug or MiniFinder, and with an
  348. ImageWriter file.)
  349.  
  350. So, concluding this discussion, I'll say that these are the methods that work for me, but you are
  351. welcome to try anything else. Mac Nosy is a good program for disassembling code you are trying to
  352. unprotect. And other protection schemes are very different from Wizardry's. So practice on some other
  353. programs and with any luck, you'll be cracking everything you can get your hands on.
  354.  
  355. Also, a few problems with the above crack I would like to note. Although it does work fine (I've
  356. killed Werdna on a cracked version), it is annoying to see the 3 dialogs at the beginning and also
  357. have it eject the disk twice. For further study, you might consider taking out the Ejects, so you
  358. don't have to re-insert the disk.
  359.  
  360. (Hint: you will not only have to take out the _Eject's, but also the routine that waits for another
  361. disk to be inserted. Since it doesnt eject any more, there isn't any way to insert a disk!)
  362.  
  363. Just to help you along, I'll give the patches to remove the ejects and wait for insert disk routines:
  364. Search for -> change to
  365. 20 5F A0 17 3E 80 4E D1 4E 56 -> 20 5F 3E BC 00 00
  366. 21 6E 00 0A 00 12 A0 17 3D 40 -> 21 6E 00 0A 00 12 4E 71
  367. 2F 2E 00 08 4E BA FF 66 A8 5E -> 2F 2E 00 08 4E 71 4E 71
  368. FF F4 66 20 48 7A 06 7E 48 7A -> FF F4 4E 71
  369. (Just search for the first part, then change the bytes that are different in the second part. 4
  370. patches in all plus the main protection patch.)
  371.  
  372. This introductory file is by no means the last word on assembly, cracking, etc. Some of the ideas of
  373. the Mac were simplified in order to bring you up to a good level of proficiency in a short time. Some
  374. of the functions do not work exactly as I outlined, but the ideas I presented are close enough for
  375. those who are beginners to the Mac world. If you are interested in the real inner workings of the
  376. Mac, I suggest getting the Macintosh Revealed books from Hayden. They explain the traps and ROM
  377. routines in greater detail.
  378. ================================================================================
  379. Copy Info
  380. There are several programs currently that don't seem to be fully crackable. By bit copying the one or
  381. two protected tracks and making a couple of patches, you can make them easily copyable, even though
  382. the original can't be copied at all. These programs all use protection from the same company, and it
  383. works like this:
  384. A nibble read of the protected track is done, then a search is made for the string ABCDEFEF where a
  385. data marker should be. They also write over low memory pointers that the debugger uses, so that the
  386. debugger will crash. Programs like this are:
  387. HARRIER, ROUGE, GRID WARS, WINTER GAMES, ETC.
  388. All have the following strings, which if you NOP them, will not destroy the debugger
  389. Search for:2489 51C8 FFF2 46C3 Change to:4E71
  390. Search for:12D8 51C8 FFFC 46C3 Change to:4E71
  391. Once you find the code that must be changed to unprotect, it is found to be encoded on the disk, and
  392. decoded just before it is used. On the HIPPO ALMANAC, the data was not only encoded, but the block of
  393. memory that it was in was reversed end for end.
  394. ================================================================================
  395. Eve Protection Scheme
  396. There is a way to get past the EVE protection scheme, but it's a bitch.From what I understand, you
  397. need to decompile the routine that checks for the dongle, and them re-assign it to check that the
  398. machine has a simple serial port as opposed to the info on the dongle itself.  That info is virtually
  399. unreadable as it's encrypted, and pretty much useless to anything except the app that's looking for
  400. it because it's mainly using for app reference.
  401. ================================================================================
  402. Faces
  403. Search for:4240 4840 80FC 0030 4840 3D40    Change to:4280 etc.
  404. It will ask you who beat Napoleon at Waterloo. The answer is Welling.
  405. or
  406. This program was pretty tough to crack until I first did Welltris. Why? Because it takes your
  407. password, stores it in memory, then compares it to the correct answer (only the first 4 digits,
  408. making the password a nice simple Long). However, if you do a simple crack it will then say bring you
  409. up to the screen with the start game button. If then checks the password again - if it's wrong, then
  410. the program corrupts itself (thanks to SAM for telling me that!). This is very similar to Welltris,
  411. so I was armed for the job.So, after the _GetIText the program pushes the return address (A5-142A)
  412. onto the stack, then your password (A5-113). A JSR then stores your password with only the first 4
  413. bytes, in lower-case at A5-142A. My simple crack simply pushes the correct password (A5-12C), instead
  414. of your password. Then, when ever the program compares what should be your  password, it's actually
  415. comparing it to itself! Har har.
  416. KRAK PROCEDURE
  417. The protection in Faces is fairly typical.  The password dialog does not affect your game, it just
  418. compares your passwords, and has a local variable to say whether to quit or not, and it also stores
  419. your password elsewhere to be checked later. 
  420. The GetIText was also really close after the ModalDialog to make cracking quite simple.
  421. This double password thing had me confused for a while because occasionaly it would corrupt on me, so
  422. I had to open the damn archive again! I knew where to go in MacsBug, yet I just could figure how it
  423. knew to kill itself!
  424.  
  425. This crack was not too advanced, yet not too simple. I thank it's creators for making the PEA so
  426. simple to find. Although this program had no definate crack point, such as an _ExitToShell, or a
  427. BNE/BEQ/TST, etc. it was fairly obvious with the BLT that it's only concerned with the first 4 chars,
  428. therefore making it easy to find where it is actually moving and comparing memory.
  429. I couldn't find the exact place to not show the Dialog, so I merely jumped over the ModalDialog
  430. routine, so you will see it flash onto the screen then disappear. That's OK. 
  431. Now, since I don't have a color Mac, I had to absolutely guess at cracking that one. It looks almost
  432. exactly the same in the copy protection routine, except it's merely a few bytes down in CODE 3. If
  433. the crack doesn't work, don't blame me, just call me at christmas, and maybe I'll have a CQD machine.
  434. Here is the complete crack:
  435. CRACK PATCH
  436. Open Faces 1.0 with ResEdit
  437. Open CODE 3
  438. Change CODE 3+$652 (just a few characters over from $650)
  439. from:    486D 01CA
  440. to:    603A 4E71
  441. AND
  442. Change CODE 3+$694 (just a few characters over from $690)
  443. from:    FEED
  444. to:    FED4
  445. Open Color Faces 1.0 with ResEdit
  446. Open CODE 3
  447. Change CODE 3+$7C2 (just a few characters over from $7C0)
  448. from:    486D 017A
  449. to:    603A 4E71
  450. AND
  451. Change CODE 3+$804 (just a few characters over from $800)
  452. from:    FEED
  453. to:    FED4
  454. ================================================================================
  455. Fileguard
  456. How to beat Fileguard!
  457. Step one: Make a system disk with norton util, AND HDT
  458. Restart machine holding down command-option-shift-delete
  459. Run HDT, select "Install HDT Driver" (on the protected, but unmmounted volume)
  460. Restart, File guard wont bother you anymore.
  461. ================================================================================
  462. Hard Disk Ejects
  463. It has come to our attention that many games are obnoxious when run (in cracked form) on a hard disk.
  464. These games cause a warm reboot and bring down the  hard disk. The solution -> use FEdit to scan the 
  465. games for OS Trap A017 (_Eject) and replace it with ADF4 ( _ReturnToFinder ).
  466. For exampleä
  467. Game Fedit    File Block    Byte# Was    Replace With
  468. MacAttack    00C    00BE    A017 ADF4
  469. Frogger    00C    005C    A017 ADF4
  470. Frogger    00D    01B4    A017 ADF4
  471. ================================================================================
  472. Image Express
  473. Background
  474. ~~~~~~~~~~
  475.      Image Express uses the Eve Protection Scheme.  Basically the protection
  476. scheme consists of 3 parts.  1) The Hardware device, 2) The Eve Init, and 3)
  477. the code inside each application which compares the values.
  478.      The hardware device which hooks up to the ADB port houses a chip that I
  479. assume has a value or a resource on it.  I say assume because I do not have one
  480. in my possession to check out.
  481.      The Eve init is basically a driver that gets installed onto the Eve at
  482. bootup.  And remains there until powerdown.
  483.      The Apps which are protected with Eve will read from the Eve and compare
  484. values, if they match it will continue on with the program as normal if they
  485. don't then a dialog will surface telling you that you either hooked up Eve
  486. wrong or the init is not installed.  If there is no Eve hooked up the same
  487. dialog will surface telling you there is no Hardware key hooked up.  etc.
  488.  
  489. Image Express is made up of 9 files in all. They are Camera, Demo Projector, Image Express,
  490. Transporter, Image Express Launcher, Camera Launcher, Projector Launcher, Transporter Launcher and
  491. Eve Init. All of these Apps except Demo Launcher are protected and have checks for Eve in there Apps
  492. at least once.
  493. The launchers all use the same exact protection scheme but I have not really worked on them too much
  494. and so I have not cracked any of them. The Eve Init is basically only values and some code in the
  495. crack I am working on the Eve Init will no longer be needed. The Camera application is somewhat
  496. tougher than the other applications; I have yet to crack it but I am slowly making progress. I have
  497. cracked the Image Express App, the Projector App and the Transporter app. Here are the hex changes:
  498. Image Express
  499. Search:3B5F F33A 4A6D F33A 6622
  500. Change:                    4E71
  501. Search:4EAD 0B62 4EAD 166A 4EAD 16DA
  502. Change:4E71 4E71 4E71 4E71 4E71 4E71
  503. Search:4EAD 257A A9F4 4E5E 4E75
  504. Change:          4E71
  505. Projector:
  506. Search:4A6D FDCE 664C 4EAD 056A
  507. Change:          4E71
  508. Transporter:
  509. Search:3B5F FBB8 4A6D FBB8 6600 01E6
  510. Change:                    4E71 4E71
  511. Search:57C0 4A00 6700 010E
  512. Change:          4E71 4E71
  513. ================================================================================
  514. Infini-D 1.0        01-1400-6350        31-9326-1679
  515. Infini-D 1.02/1.1.1        31-9326-1679
  516. Infini-D 1.02
  517. Protection Scheme: Serial Number
  518. Supplier: Far Side
  519. Problem : Ok, a cool user on my board, Far Side, logged on new and since I was around spying on him,
  520. I decided to validated him before he got on. I should do, Infini-D1.02. I unpacked it and booted it
  521. sometime thereafter and noticed that the first thing that happens is a Serial Number Registration box
  522. comes up and asks me for my Name, Organization and Serial Number. Ug. Playing around with it, like I
  523. usually do, I noticed that if you try to hack out a Serial Number, it will just stay there like
  524. nothing happened. This is useful in determining how to go about cracking it because now I know I can
  525. not just search for an _ExitToShell Trap (Hex-A9F4). By the way, I tried putting in some earlier
  526. version's serial numbers but they do not work on the new version (1.02) at all.
  527. Solution : So I cancelled out of the registration thing and got back to the Finder where I jumped
  528. into MacsBug. Then I set a trap for _InitGraf (Hex-A86E) which is usually the first Trap executed by
  529. every program to init the graphics screen and what not. From here I double-clicked the App (Infini-D
  530. 1.02) and the cursor changed a little and found the trap. I scanned through a little, going nice and
  531. slow as to be careful noticing which JSR or JMP or branch would be the one to go to the Registration
  532. dialog. I went a little further, then it happened, so I went into MacsBug and found this as the last
  533. instruction before the dialog box appeared:
  534. Addr    Instruction    Hex Bytes
  535. Who Cares    JSR  $0798    4EBA 0796
  536. Ahh! How easy? It's a JSR, so all we have to do is change those bytes (4EBA 0796) to two No
  537. Operations (4E71 4E71). This crack was extremely easy, to tell you the truth. But it was fun none the
  538. less. I hope you enjoy it.
  539. Hex Changes:
  540. Search for: 4EBA 0796
  541. (You should find this 2 times, at Sectors 392 & 3FE)
  542. Change to : 4E71 4E71
  543. ================================================================================
  544. MINIFINDER ZAP
  545. For 3390 byte MiniFinder created Feb. 19, 1904 4:40 AM by CCOM. (If you don't have this version don't
  546. even think of trying the following.) Important note! Use Fedit or an equivalent to zap the file.
  547. Block 1, positions 88 and 89 contain the number of file types that MiniFinder looks for on a disk.
  548. Change Block 1 Position 89 from $01 to $02. Block 5, positions 408 through 416 contain the type list
  549. and other apparently useless information (I zeroed almost everything out and it still worked). Change
  550. Block 5 Positions 408 to 416
  551. From: $00 $00 $6D $46 $69 $6E $64 $65 $72
  552. To: $46 $4E $44 $52 $00 $00 $00 $00 $00
  553. And that's it!
  554. Now The Finder of other disks will appear in the scoll window of MiniFinder when it runs. One problem
  555. though, make sure you have two drives. When the Finder of another disk is chosen to be opened,
  556. MiniFinder begins to execute it and then asks for the disk MiniFinder is on to be inserted into a
  557. drive if it is not online. If you do this by having to eject the disk with the Finder that you wnat
  558. to boot, MiniFinder gets confused and crashes.
  559. ================================================================================
  560. MultiDisk Partition Cracks
  561. Hereπs how to do a MultiDisk Partion Crack:
  562. The way you "crack" Performer is with MultiDisk.  If you don't know what I
  563. mean by that, he is the routine.  Install The MultiDisk INIT, and DA.  Reboot. Go to the DA.  Create
  564. a partition that is a little bit large than Pedrformer (and it's few extra files) needs.  Mount it. 
  565. Insert the Perfromer disk.  Make sure it is NOT write protected.  Launch off the floppy.  It will
  566. take you first to the HARD DISK INSTALL screen.  Install onto the partition.  Quit the installer. 
  567. Unmount the FLOPPY.  Check out the partition, see if the install works (it will...).  Drag the
  568. partition to the trash (unmount it.).  Open MacTools, etc., or whatever program you have that will,
  569. 1- let you see invisible files, and, 2- let you "uncheck" tthe invisible box, so as to make them
  570. visible on the desktop.  Find the MultiDisk partition.  It will be called, "MultiDisk
  571. Partition000000xxxxx"  (lots of numbers, no matter...). Make it visible.  Quit MacTools.  Back to
  572. Finder.  Finder the partition FILE. Drag it into a folder.  VERY IMPORTANT, you must get this file
  573. off the desktop, by dragging it into a folder.  If you don't, it will not copy properly!  Open the
  574. folder you put it in.  Slect the file.  Hit command-D, and enjoy watching it copy.  Do it again,
  575. even.  The last few numbers on the file will get replaced with the word copy.  No worry, just delete
  576. the letters c-o-p-y, and all will be ok.  Now, get your floppy install back, so you can return it to
  577. whoever let you borrow it.  Drag one of these copies out of the folder, open MultiDisk DA, and mount
  578. it.  Insert the orig floppy.  Launch off the floppy, as before.  This time, REMOVE the install.  Quit
  579. installer.  Take out the floppy, write protect it, and give back to friend.   It is now as it was
  580. before.  Drag the partition to the trash (unmount).  Also, Drag the MultiDisk FILE (the one on with
  581. all those numbers) to the trash.  After all, you just removed the install from it, it is now
  582. worthless.  Drag another one of the copies out of the folder, use the DA to mount it, and you now
  583. have Performer (or Vision, or anything else you desire).  Copy protection bites the dust!!!!   NOW,
  584. the files here on the Nest, like Performer, Vision, etc., are already partitions, you only need to dl
  585. MultiDisk.  Make sure you keep a backup of MultiDisk, it likes to corrupt itself once in a while, and
  586. it will freak out if you are one a network.
  587. ================================================================================
  588. Network Protection Scheme
  589. Cracking a Network protection scheme is pretty easy. Registration on any LocalTalk network has to be
  590. done by a single ROM call NBPRegister. The passed parameters to NBPRegister consist of a pointer to
  591. what is called an ABusRecord and a Boolean. Ignore the Boolean and look in the ABusRecord for another
  592. pointer called the nbpEntityPtr. (The newer versions of Nosy should decode these data structures for
  593. you.)  Now find the data that is being passed in with the nbpEntityPtr (look for a PEA instruction),
  594. go to that data which will consist of a packed set of bytes corresponding to name:object:zone. Change
  595. the name, leaving object and zone alone. Presto Jerry and the thing now cannot recognize itself as
  596. self.
  597. ================================================================================
  598. Painter 2.0        0011187QBO (The last 3 are letters)
  599. It's a bit of a tough one for you to try as a first crack, anyways i looked atit briefly the other
  600. day and this seemed to work, later i realized that saving and printing didn't work and so it must
  601. have gone to demo - i made no attempt to comprehend or decompile what the hash routine was, rather i
  602. simply tried to disable ever single check, so that wrong means right type thing.  I'm sure this is
  603. very close to the real thing that is needed.
  604. Painter 2.0
  605. GWIL
  606. GWIL    main     CHANGES
  607. +21A     +FE     6718->6018
  608. +286    +16A     6FB8->4E71
  609. +2E2    +1C6     6FAC->4E71
  610. +322    +206     6600 FEF8 -> 4E71 4E71
  611. +3DA    +2BE     6EB6->4E71
  612. +40A    +2EE     670C->4E71
  613. CODE 2
  614. +12EA  6600 FE46 -> 4E71 4E71
  615. +131C  6FDB -> 4E71
  616. +134C  6FD8 -> 4E71
  617. oh and a tip , whenever using this type of crack info use resorcer instead of resedit as it has a
  618. better faster interface.  Also whenever you encouter code in a non-"CODE" resource, simply go to the
  619. preferences in resorcerer and tell it that , in this case "GWIL" is a pseudonym for "CODE".  ie add
  620. "GWIL" to the list, then you can view it as a code resource.
  621. ================================================================================
  622. Panorama II
  623. Crack
  624. I jumped into MacsBug and set a trap for _InitGraf, which is normally how ever program starts off. It
  625. went fine and I traced the code, but unfortunately, after tracing through, it killed me back to the
  626. Finder. They obviously protected against tracing. No prob, I clear the trap table, and then rung up
  627. an _ExitToShell trap. Then I ran the program and hit return and MacsBug caught the _ExitToShell call
  628. being executed. It looked something like this:
  629. Addr    Instruction    Hex Bytes
  630. 004A55A4    _ExitToShell    A9F4
  631. 004A55A6    CMPI.L #$00000001,-$6F52 (A4)    0CAC 0000 0001
  632. 004A55AE    BNE.S  +$001C    661A
  633. So, I wrote down the hex bytes for a backup and then went to DisAsm to scan for _ExitToShell traps
  634. (A9F4 in Hex). I found 2 right off the bat but they weren't the ones I was interested in because they
  635. didn't have the same bytes following them as the code above. So I kept on searching until DisAsm
  636. bombed into oblivion with an "Out of Memory xxxx" error or something or other. I hate that! In any
  637. case, I booted up my FEdit+ 3.21 and searched for the bytes I needed and found them on sector 494 of
  638. the Panorama Application. So I changed the ExitToShell Trap (hex A9F4) to a NOP (hex 4E71) and booted
  639. the program. The configuration dialog came up again and when I hit return, the program didn't quit
  640. but went on to the rest of the program the right way. The APP was CRACKED! Yes! But like every good
  641. cracker knows this crack was half ass because the dialog should not even come up in a well cracked
  642. ware. So I went back to FEdit and looked around at where I made the changes. And found out a couple
  643. of bytes before where I made changes was where the program put the dialog up. So here are the
  644. complete changes to the COMPLETE Panorama II Crack:
  645. Hex Changes
  646. Search for: 6730 4EBA 02E8 4AAC 90AE 6602 A9F4 (Found on sector 494)
  647. Change to : 6730 4E71 4E71 4E71 4E71 4E71 4E71
  648. And the sn# is not the only thing you need to run panorama II. Your Name, Company, Phone #, and SN#
  649. are coded into the application so you need to use the crack.
  650. But if you want your name SN# etc. in the program just look for the Panorama II prefs in the Prefs
  651. folder and if it's there delete it. Then run a virgin copy of Panorama II and type in anything you
  652. want and say (OK or Cancel) then patch the Program and the patched Program uses the Pref file you
  653. created in the Prefs folder and Voila
  654. ================================================================================
  655. QuickFormat 7.0
  656. Protection Scheme: Key Code Required to use special features
  657. Scenario
  658. Ok, I was calling around a few boards and as usual I make my rounds on the Buzzard's Nest(s). When
  659. calling BN Central I noticed someone posted asking me to remove the protection scheme from Quick
  660. Format 7.0. So I got it, and I have finally gotten around to cracking it today. Oh well, sue me!
  661. Problem
  662. When launching the program an annoying dialog box comes up asking you to register the program with a
  663. KEY CODE to use the advanced features of the package. If you typed in an INVLALID key code it will
  664. let you use the program with the few less sophisticated functions.
  665. Solution
  666. So I quit out of the program and then jumped into MacsBug. I set a trap for the _INITGRAF (Hex-A86E)
  667. and I double-clicked the Quick Format 7.0 Application.
  668. I traced through to a very suspicious part of code that looked something like this:
  669. Addr    Instruction    Hex Bytes
  670. 583834    JSR SETUPMEN    4EBA FE14
  671. 583838    JSR INITIALI    4EAD 02E2
  672. 58383C    JSR INITGLOB    4EBA FEBE
  673. 583840    JSR VIRALCHE    4EBA FF22
  674. 583844    JSR CHECKMOD    4EBA F82A
  675.  
  676. Now, its pretty obviouse from just looking at the labels that they used that you can determine what
  677. is going on. In most cases people would not use LABELS like the ones used above, but since it is
  678. shareware and not a $500 commercial package I can see why the author opted the easier route for
  679. programming ease. The first JSR would probably be him initializing his menus and stuff. The second
  680. JSR would be to initialize the screen and the fonts or whatever, the third JSR would be Initializing
  681. the global variables he would need and the fourth would be to check for any virus, persay. The fifth
  682. however is the routine he uses to check if the program has been Registered and brings up the dialog
  683. asking you to enter a key code. If it hasn't be registered with the correct keycode the program turns
  684. off some options. But, that is not necessary, as by omitting this JSR CHECKMOD you will remove the
  685. check and the program will run with all options available. Neat, eh?
  686. Byte Changes (You should find the SEARCH string only ONE TIME!)
  687. Search:    4EBA FE14 4EAD 02E2 4EBA FEBE 4EBA FF22 4EBA F82A
  688. Change:    4E71 4E71
  689. QuickFormat 7.1
  690. CODE 3 +$3B6  From $6606 to $4E71
  691. ================================================================================
  692. Railroad Tychoon
  693. Find Hex string 0684 6646 486E and replace it with 0684 4E71 486E. When you hit the choose the
  694. locomotive screen, any choice you make will be valid. I've since heard that the krak listed above
  695. allows the game to continue to limit your play to two trains at a time. A bad krak in other words.
  696. Protection Background
  697. I sat down here a few hours ago with the intention of blasting a quick hole in the protection. It's
  698. now five in the morning. This is a questionable krak. The first anonymous attempt reportedly didn't
  699. work. I'm not sure if this second attempt (mine) will work either. Understanding why means taking a
  700. much closer look at the logic of the program.
  701. Krak Procedure
  702. The protection in Railroad Tycoon is not typical. The screen that comes up asking for you to identify
  703. the type of locomotive is crucial to the operation of the protection. It's also very difficult to
  704. remove from the flow of execution - at least I haven't been able to sidestep it. Your choice sets up
  705. certain values in certain global variables for the program to use later.
  706. There are two separate response handling routines. One routine, called BCONTENT (accessed by a JSR
  707. CA(A5)), handles the response if you click the mouse. This routines highlights the name choices of
  708. the locomotives as you click them. It will also handle a click on the OK button. The other routine,
  709. called BKEY (accessed by JSR E2(A5)), handles keyboard input. I suppose it's possible, though I
  710. haven't tried, to choose the locomotive name under the direction of the arrow keys. This second
  711. routine also handles a return (hit OK).
  712. This double routine thing had me confused for at least an hour because I would randomly (and
  713. unconsciously) choose the OK button, sometimes with the mouse and sometimes with the keyboard. I kept
  714. setting breakpoints where I knew execution would occur (I knew this because I had painstakingly
  715. traced through the whole code block, picking out good breakpoints), but I had only done so for the
  716. mouse routine. I kept confusing myself by randomly selecting the OK button with the keyboard
  717. (sometimes TMON would break in, sometimes it wouldn't, on a seemingly random basis)!
  718. I began looking at the protection with the idea that the protection was a subroutine. It is not. The
  719. whole initialization of the game is all in one routine, with the protection at the leading edge of
  720. the code segment. This pre-misconception (at midnight) proved time consuming. (I'm telling you about
  721. all these traps I fell into so you can use the experience in your kraks.) The fact that the
  722. protection is built into the main initializing code segment makes the whole approach to kraking it
  723. much more involved.  As I said above, I was looking for a "quickrak" [hmmm, a new word], but this
  724. just was not going to be the case.
  725. I stubbornly kept looking for a definitive krak point - one of those luscious, helpful, welcome
  726. conditional branches that, when satisfied, completely jumps around an undesirable bunch of code (the
  727. code bunch that says, "Nope. You're either blind or a pirate with no manual, so you will have only
  728. two trains"). At about four o'clock, it finally dawned on me (pardon the pun, the sun is just coming
  729. up now as I type this) that the protection was hard-wired into the logic of the program. When I say
  730. this, I mean that there is not any clear-cut result from your choice.
  731. In particular, this protection scheme (as I said above, or at least think I said above) takes your
  732. choice and puts a bunch of corresponding values into a bunch of global variables. Later on, the
  733. protection code then goes on and does a bunch of math operations on those values to come up with, not
  734. a condition, but data addresses and pointers for a dialog box.
  735. The protection always draws a dialog box (regardless of whether or not you make the right choice).
  736. The only thing that is different when you make the right choice is the contents of that dialog box,
  737. as computed from the numerical values assigned to your choice.
  738. Are you confused? The protection is not saying yes and it's not saying no. It's using your choice to
  739. figure out what to say in its dialog box (the gray one that pops up right after you make your
  740. choice). Because figuring out all that crumby math logic is way beyond my effort limits (especially
  741. for a game like this), the program always fills its dialog box with the message corresponding to an
  742. incorrect choice. The protection always tells you that you will be limited to two trains and there is
  743. nothing I am going to do about it.
  744. A bit farther down in the code from the _ModalDialog (the trap call which waits for you to
  745. acknowledge reading the dialog box's message with a return) is one of those luscious, helpful,
  746. welcome conditional branch statements I'm always looking for. Need I say that I was very happy to see
  747. it?
  748. I changed the BNE at "BSWITCH"+AC4 to an NOP. Here's where the ambiguity comes in. I think this
  749. modification forces the program to always act as if you've made the correct choice for the
  750. locomotive's name. (If this modification does in fact do this, then it constitutes a "krak"! If it
  751. does not, well, then it's your turn to take a shot at this thing.) In more words, despite the fact
  752. that the program's dialog box says you've made the wrong choice and will be limited to only two
  753. trains, this little "krak" makes the program a liar. You should be able to play without any software
  754. protection limitations to the number of trains.
  755. To be honest, I do not have the patience right now to figure out the game, to play it, or to test the
  756. krak. I'm way too tired. Additionally, I feel fairly certain that I will not have the slightest
  757. interest in figuring out the game, to play it, to test the krak tomorrow, or the next day, or even
  758. the next day. (I dunno. I'm hedonistic when it comes to computer games. People tell me Robot Wars and
  759. SSI games are great. I tell them they're nuts - I'm action arcade all the way. Besides, nothing turns
  760. me off faster to a game than a pathetically slow opening graphics presentation, and Railroad Tycoon
  761. definitely takes the cake (and whole damn cooking pan and spatula) when it comes to pathetically slow
  762. opening graphics presentations!  Have you ever seen anything slower?!?)
  763. In all fairness (actually curiosity), I went back and looked through the game for the krak patch that
  764. Grimm posted. It's there all right, but I believe it is in the wrong place. If you search for what he
  765. says, but search for it twice, the second occurrence is remarkably close to where my krak patch is.
  766. Krak Patch
  767. Hex search for:
  768. 28 00 02 B0 69 06 84 66 08 08 AD
  769. Hex change the bold values to 4E 71
  770. This should appear on sector 301, byte 25848 of the file.
  771. or
  772. Find Hex string    0684 6646 486E
  773. Replace it with    0684 4E71 486E
  774. When you hit the choose the locomotive screen, any choice you make will be valid The krak listed
  775. above allows the game to continue to limit your play to two trains at a time.
  776. ================================================================================
  777. Claris Resolve 1.0
  778. Protection: Date Expiration
  779. Supplied by: Zelig
  780. Problem: Resolve will expire August 10, 1991 unless a valid serial number is entered.
  781. Solution: I was having problems finding out where the check was taking place so I went the easy route
  782. and set a trap in MacsBug for an _ExitToShell (A9F4) and then back traced using "IL" to list the code
  783. before the _ExitToShell. And this is what was revealed:
  784. PEA $FFFC    ;486E FFFC
  785. JSR Timebomb    ;4EBA FCF6
  786. Now, this is extremely suspicious. All you have to do is change the JSR Timebomb to NOPs and a branch
  787. right afterwards that will make Resolve work forever.
  788. Hex Changes:
  789. Search : 486E FFFC 4EBA FCF6 4A00 588F 670E
  790. Change :           4E71 4E71           600E
  791. ================================================================================
  792. Shutdown Code
  793. For you people with hard disks and are running MacBugs or apple debugger and when you crash and are
  794. not able to exit to shell (Finder) here is the code to type to unmounted all volume and then do a
  795. shutdown this will help to recover faster by not having to rebuilding the desktop after your crash:
  796. SM A78 3F3C 0002 A895 (THEN A RETURN)(YOU HAVE TO PUT THE SPACES IN)
  797. G A78 (THEN ANOTHER RETURN) (YOU JUST DID A SHUTDOWN NOW)
  798. ================================================================================
  799. StuffIt Lite 3.0
  800. If you have a registerred copy of Stuffit Lite 3.0 and you want to change the registration info,
  801. change the serial number that is in the data fork of the Stuffit Lite 3.0 application at the offset
  802. 836 ($344) from the start of the data fork (which is at the end). The registration name is in the
  803. middle of the data fork.
  804. If your copy of Stuffit Lite 3.0 has been patched by the Stuffit Lite 3.0 crack program, you can
  805. change it back to normal by changing CODE 13+$1208 from $4E71 to $6622. Unpatched Stuffit Lite
  806. programs won't have the same CODE 13 resource (see next paragraph). I tried this patch before I got
  807. the Stuffit Lite 3.0 crack and found that it didn't enable encryption or multiple open files so it
  808. was useless. I threw away the Stuffit Lite 3.0 crack because of this and it did the same thing I
  809. already tried.
  810. Stuffit Lite 3.0 contains some compressed resources that include most CODE resources (including CODE
  811. 13) and some DITL resources and probably others. (This is why trying to compress the file only gives
  812. about 3% saved.) This compression effectively scrambles them so they appear virtually meaningless.
  813. Stuffit uncompresses them when you run the program. The CODE 13 resource that was used in the patch
  814. was an expanded version of the CODE 13 resource in unpatched programs. The person who made the patch
  815. got the uncompressed resources from memory when the program was running and worked with them. (I made
  816. an FKEY that will retrieve resources from memory). You can't patch your unpatched program without the
  817. expanded CODE resource or the crack program. Surprisingly, Stuffit doesn't care if it's resources are
  818. expanded even though they should be compressed.
  819. Here are the serial numbers. They were created using numbers from 0 to 199.
  820. (most should work):
  821. L297000000    L347000001    L397000002    L447000003    L497000004    L547000005
  822. L597000006    L647000007    L697000008    L747000009    L267000010    L317000011
  823. L367000012    L417000013    L467000014    L517000015    L567000016    L617000017
  824. L667000018    L717000019    L237000020    L287000021    L337000022    L387000023
  825. L437000024    L487000025    L537000026    L587000027    L637000028    L687000029
  826. L207000030    L257000031    L307000032    L357000033    L407000034    L457000035
  827. L507000036    L557000037    L607000038    L657000039    L177000040    L227000041
  828. L277000042    L327000043    L377000044    L427000045    L477000046    L527000047
  829. L577000048    L627000049    L147000050    L197000051    L247000052    L297000053
  830. L347000054    L397000055    L447000056    L497000057    L547000058    L597000059
  831. ================================================================================
  832.  
  833. 
  834.  
  835. This document is a short tutorial designed to prepare the reader to use TMON and MacNosy to render
  836. protection schemes inoperative.  It will not prepare the reader to begin programming in assembly
  837. language, in fact, I am not a programmer myself.  Hopefully this will allow someone with a minimum
  838. programming background to learn how to quickly read assembly listings, and then quickly locate a give
  839. protection scheme.  Actual cracking will not be covered in detail in this document.
  840. The following topics will be discussed in detail:
  841. Number Systems and Memory
  842. Basic Architecture and Addressing Schemes
  843. Instruction operands and parameters
  844. The Flags Register
  845. The Stack
  846. Traps
  847. Assembly Mnemonics
  848. How To:  MacNosy
  849. Example Code
  850. How To:  TMON 2.8.x
  851. How to Crack Sorcerer:  A Test Cruise.
  852.  
  853. THE BASICS
  854.  
  855. Number Systems
  856. We will be dealing with three different number systems.  The difference between the number systems is
  857. simply at which number one decides to carry into the next column.  In Decimal (the first system), we
  858. carry at the 10th number.  That is, any given digit can only hold 10 values, namely, the numbers 0 -
  859. 9.  Once we get to the carry value, we carry a one into the next column and reset the previous column
  860. to zero which is precisely what happens when you go from 9 to 10 (or 99 to 100 in which you carry
  861. twice, etc).
  862. The second number system is called binary.  In this system, the carry value is 2.  This means that a
  863. given digit (called a bit in binary) can hold 2 values: 0 and 1. To add one to a number in binary,
  864. you use the same principle as in decimal, except that the carry is a different value.  To add 1 to 8
  865. in decimal, you just add 1 and there is no carry (because the ones column hasn't reached the carry
  866. value (10) yet).  To add 1 to 9 in decimal, you have to carry the one to the next column (because you
  867. have passed the carry value) and reset the ones column to 0.  So, counting in binary looks like this:
  868. 0
  869. 1    Add one to zero: we haven't reached the carry value (2) yet.
  870. 10    Add one to one: now we have 2 so we have to carry one to the next column and reset the first
  871. column.
  872. 11    Add one to zero (in the first column) and you just get one.
  873. 100    Add one to the first column and you get 2 so carry 1 to the second column and zero the first
  874. column.  Add the carried one from the first column to the second column and you are adding 1 + 1
  875. which is 2 - carry again.  So, carry the one to the third column and zero the second column.
  876. 101    And so on...
  877. 110
  878. 111
  879. 1000
  880. 1001
  881. 1010
  882. 1011
  883. 1100
  884. 1101
  885. 1110
  886. 1111    And here we are at 15 decimal.
  887.  
  888. OK, we refer to binary because it is the native numbering system of the computer and also because in
  889. some of the instructions, the individual bits represent different information.  Unfortunately, binary
  890. is hell for us humans.  That brings us to the third major numbering which is hell for the computer
  891. AND hell for us!  But both sides can deal so it's not too bad.
  892.  
  893. Hexadecimal is the third system and its carry value is, of all things, 16.  Now, we don't have 15
  894. digits so hexadecimal uses the letters A-F for its last values.  Here is how to count in hexadecimal;
  895. Hex    Decimal    Binary
  896. 0    0    0
  897. 1    1    1
  898. 2    2    10
  899. 3    3    11
  900. 4    4    100
  901. 5    5    101
  902. 6    6    110
  903. 7    7    111
  904. 8    8    1000
  905. 9    9    1001
  906. A    10    1010
  907. B    11    1011
  908. C    12    1100
  909. D    13    1101
  910. E    14    1110
  911. F    15    1111
  912. 10    16    10000
  913. And so on.  You may be wondering what the hell is so great about hex numbering.  Well, it turns out
  914. that one hex digit can account for 4 binary digits (whereas decimal cannot hold a whole number of
  915. binary digits).  This makes it extremely easy to convert binary to hex and back.  To convert to hex
  916. from binary, just take the right-most 4 digits and convert it to its equivalent hex digit with the
  917. above table.  Then do the same for the next 4 binary digits and keep going until you are out of
  918. binary digits.  For example: 1010111000110001101.  Break it up as follows:  101  0111  0001  1000 
  919. 1101 and convert each group of 4 into a hex digit:  6  7  1  8  D so the hex number is 6718D.  Easy
  920. right?
  921. To go back to binary, take each individual hex digit and convert it to its equivalent binary code.
  922.  
  923. Signed Numbers and 2's Complement.
  924.  
  925. The basic binary system has no way of representing negative numbers.  To accomodate this, we use what
  926. is called a sign bit.  The sign bit is simply the leftmost bit we a talking about (meaning that often
  927. we have a 32 bit piece of data, but only care about 8 or 16 of the bits - so the sign bit is the 8th
  928. or 16th bit respectively), and is set to one for negative numbers.  This means that if you want an 8
  929. bit number to be negative, then it's eighth bit must be 1 (and 16th bit must be one for 16 bit
  930. numbers, etc.).
  931. Two's Complement is an operation (yes there is an assembly instruction to perform it) that converts a
  932. positive integer to its negative equivalent (e.g. 1 to -1, 5 to -5, etc).  To perform it, simply
  933. invert every bit in the number, then add a binary 1 to it.  Take the number 00000001 (the eight bit
  934. integer 1).  To make this -1, invert every bit (11111110) and add binary 1 to it -> 11111111.  This
  935. then is -1 (or FF hex) as an eight bit integer.  What happens if we want to treat this as a 16 bit
  936. integer?  Big trouble, because now the sign bit is bit 16 and god only knows what is in bit 16.  So,
  937. assembly has an instruction called Extend that extends a number out any number of binary places to
  938. make sure that any bits to the left of the original number don't affect its value.
  939. All of this is relatively unimportant, since the assembly program you are trying to crack has already
  940. taken care of all these details and I have yet to see this type of information be critical to the
  941. cracking process.  I simply wanted to get this out in the open so that you will have a better
  942. understanding of some of the instructions that will come up in the assembly instruction listings.
  943.  
  944. Now let us start by talking about memory.  You probably already know that there are two kinds: ROM -
  945. Read Only Memory - and RAM - Random Access Memory.  As crackers, we don't care about ROM since we
  946. can't change it.  Memory is one of the two things that we can move information into and out of (the
  947. other being CPU registers explained below).  Each individual piece of memory has its own address
  948. which is simply one number from a sequential list of all available memory (i.e. it starts at zero,
  949. and goes up to the end of memory).  The address is the means of telling the processor which piece of
  950. memory we are talking about.  For example, if we want to execute a piece of code, we need to tell the
  951. processor the address of the memory that the code starts at.
  952.  
  953. Basic Architecture and Addressing Schemes
  954. CPU Registers
  955. The 680X0 processors contain 8 data registers and 8 address registers.  You can think of a register
  956. as a variable if you like; basically it is a storage unit that can hold up to 32 bits (binary digits)
  957. of information - or 4 bytes.  Note that the programmer is not required to use all 32 bits; in fact
  958. most assembly operators can be used on 8, 16 or all 32 of the bits.
  959. The Data registers are labeled D0 through D7 and are used to hold data that will be operated upon.
  960. For example, mathematical operators (e.g ADD, SUB[tract] ,etc.) operate on data registers.  
  961. The Address registers are labeled A0 through A7 and are used to hold memory addresses. This is how
  962. assembly language treats pointers.  Pointers are simply a tool for easily dealing with a particular
  963. section of memory.  If an address register contains an address, then that register can be used to
  964. move things into and out of the memory address that it contains (i.e. the memory that it points to).
  965. It is important to remember that ANY register simply contains 32 bits of information.  There is
  966. actually no difference between what is contained in a data register and what is contained in an
  967. address register.  In fact, information can be moved between the two directly.  The reason we call
  968. D0-D7 data registers, is because there are no commands to deal with their contents as addresses.  And
  969. we call A0-A7 address registers because all the address commands apply to them.
  970. Addressing Schemes:
  971. The idea here is to understand some of the ways that information can be moved into and out of
  972. registers and memory itself. I will give some very short programming examples to illustrate both the
  973. syntax and the use of a given scheme.  I will be using the MOVE instruction which simply moves the
  974. first argument into the second argument:
  975. for example:  MOVE 100,D1
  976. moves the number 100 into the data register D1.  You might be wondering whether 100 is binary,
  977. decimal, or hexidecimal.  Well, right now we don't care, but as a general rule, we will assume that a
  978. number is decimal, unless it is prefixed by a dollar sign $.  TMON and Nosy will be very explicit
  979. about telling you what type of number the command is using - but more on that when we talk about TMON
  980. and Nosy.
  981. BTW, this list is not the offical set of addressing schemes.  I have grouped similar schemes into
  982. larger groups.  For example, there is immediate addressing which means that you are moving a value
  983. (not a memory address or register).  I have grouped immediate addressing with direct addressing since
  984. it does the same thing.
  985.  
  986. Direct Addressing:  This is simply the moving of information directly into a register or memory
  987. address.
  988. Examples:    MOVE    100,D1    ;100 is in decimal
  989.     MOVE    D1,D2
  990.     MOVE    D0,100    ;A little different here: since 100 is the receiving address (the second one) it
  991. will be treated as a memory address.  So this instruction moves the contents of D0 into memory
  992. address 100.
  993.     MOVE    $55,D5    ;$ indicates 55 is in hexadecimal
  994.     MOVE    $97BA54,A1    ;moves the hex address 97BA54 into A1.
  995. Remember here that the last two instructions are essentially the same.  They both move some number
  996. into a register.  However, the last instruction - since it moves the number into an address register
  997. - is setting up a pointer and a whole host of new instructions become available to it that are not
  998. available to the D registers.
  999. Later we will note that there are several parameters that can be attached to the MOVE instruction
  1000. (and many other instructions, for that matter).  These will be covered later.  This section is simply
  1001. to show you how various kinds of information is manipulated.  Note that in Direct Addressing, you see
  1002. exactly what it is that is being moved: in the first example, you can see directly that the decimal
  1003. number 100 is being moved into register D1.  Any subsequent operations on D1 will involve the number
  1004. 100.
  1005. Indirect Addressing: (extremely important)
  1006. This scheme involves moving some address into an address register and then operating not on the
  1007. number in the address register, but rather on the address that is contained in the address register.
  1008. Example:    MOVE    100,(A1)    ;moves the decimal number 100 into the address pointed to (or
  1009. contained in) by A1.
  1010. Re-examine the last example of Direct Addressing.  The command moved the number $97BA54 into address
  1011. register A1.  Since it is an address register, we can think of $97BA54 as an address rather than just
  1012. a number.  It may well be just a number, but odds are it will eventually be used as an address.  The
  1013. instruction above moves the decimal number 100 into the address $97BA54.  It does not move the number
  1014. 100 into address register A1.  The parentheses mean that whatever is in A1 is actually an address and
  1015. that this memory address will now contain the number 100.
  1016. Example:    MOVE    (A1),$1000    
  1017. This instruction looks at the contents of A1, treats the contents as a memory address, and gets
  1018. whatever is contained in that address and moves into hex address 1000.
  1019. Example:    MOVE    (A1),(A2)
  1020. This instruction looks at the contents of A1, grabs the contents of the address it contains, and
  1021. places this value into the address pointed to by A2.
  1022.  
  1023. Lets look at a simple program and examine the memory that it deals with:
  1024.     MOVE    100,D0    ;move 100 into D0
  1025.     MOVE    $5000,A1    ;move address $5000 into A1
  1026.     MOVE    D0,(A1)    ;move D0 into address in A1
  1027.     MOVE    D0,A1    ;move D0 into register A1
  1028. Ok, let's analyze this sucker.  First off, we move the decimal number 100 into data register D0.  Any
  1029. further references to D0 will also be references to the number 100.  The second instruction moves the
  1030. hexadecimal number 5000 into address register A1. Since we are dealing with an address register, we
  1031. can think of $5000 as the memory address $5000.  The third instruction says to move the contents of
  1032. D0 (which is the number 100) into the address contained in A1 (which is the address $5000).  So after
  1033. this instruction, if you looked at memory address $5000, you would see the number 100.  The last
  1034. instruction serves to illustrate the difference between direct and indirect addressing.  This
  1035. instruction move the contents of D0 (still 100) directly into register A1 (and not into memory
  1036. address $5000, as the previous instruction did).  After this instruction, if you looked at the A1
  1037. register, you would see the number (or address since it is an address register) 100.  After this last
  1038. instruction, if you repeated the third instruction, the number 100 would be moved into memory address
  1039. 100 (since we just changed the address contained in register A1).
  1040.  
  1041. Consider an assembly program that needs to fill a block of memory - let's say from address 100 to 200
  1042. - with the number 10.  To do this with direct addressing would require the following:
  1043.     MOVE     10,D0        ;D0 now contains the fill number.
  1044.     MOVE    D0,100    ;put the number 10 into address 100.
  1045.     MOVE    D0,101
  1046.     MOVE    D0,102
  1047. and 97 more move instructions to directly move the number 10 into the appropriate memory addresses. 
  1048. Now consider the same program using indirect addressing (here I will use some psuedo-code to fill the
  1049. loop structure):
  1050.  
  1051.     MOVE    100,A0    ;put first address into A0.
  1052.     While A0 not equal to 200 do the following:
  1053.         MOVE    10,(A0)
  1054.         Increment A0 to next address
  1055.     End While Loop.
  1056. Note that this program is much simpler.  Once the address register is set to the correct address, we
  1057. can move the number 10 into this address then just increment the value in A0 which effectively makes
  1058. A0 point to the next address.  Note also that we could have MOVEd the number 10 into D0 and then
  1059. inside the loop MOVEd D0,(A0) which would have had the same result but with one more instruction.
  1060.  
  1061. Auto Increment Addressing:
  1062. This is not actually a distinct scheme, rather it is a slight modification of the indirect scheme. 
  1063. The idea is to automatically update a pointer simply by referencing it.  There are two flavors of
  1064. this:  auto pre-decrement, and auto post-increment.  Pre-decrement first decrements the register in
  1065. question, while post-increment increments the register after the instruction is finished.  It looks
  1066. like this:
  1067.     MOVE    D0,-(A1)    ;decrement A1 to the previous address and put the contents of D0 into this
  1068. new address.
  1069.     MOVE    D0,(A0)+    ;move D0 into address pointed to by A0 and then increment A0 to point to the
  1070. next address.
  1071.     MOVE    (A0)+,(A1)+    ;move the contents of memory pointed to by A0 into the memory address pointed
  1072. to by A1 and then increment both registers.
  1073. Now lets look at the previous program to fill a block of memory:
  1074.     
  1075.     MOVE    100,A0
  1076.     While A0 not equal to 200 do:
  1077.     MOVE    10,(A0)+    ;fill the address and increment to next address.
  1078.     end while loop.
  1079. In this program, we use the auto post-increment to automatically increment register A0 to the next
  1080. address that we will be using.  This type of program structure is often used to move and compare
  1081. passwords around in memory.  Let's say the password is residing at memory address $A000 and that we
  1082. need to move it to address $B000 before we call a routine that checks to see if is the correct one. 
  1083. Here is a program we might use:
  1084.  
  1085.     MOVE    $A000,A0    ;put source address in A0.
  1086.     MOVE    $B000,A1    ;put destination into A1.
  1087.     MOVE    (A0)+,(A1)+    ;move one piece of password to destination and increment both pointers.
  1088.     MOVE    (A0)+,(A1)+    ;move next piece of password to destination.
  1089. The third line moves the first half of the information from $A000 to $B000.  After both registers are
  1090. incremented, the registers contain $A002 and $B002 respectively and are ready for the next piece of
  1091. the password to be moved (assuming the password was 4 bytes long).  Now why, you are asking, did the
  1092. auto-increment add two to the two addresses instead of just one?  Well, check out the next section on
  1093. data size parameters to find out.
  1094.  
  1095. This about wraps up addressing schemes and register introduction.  Next I want to look at one
  1096. instruction - MOVE - and consider all the parameters one might use with it.
  1097. The first thing to consider is that there are several types of MOVE instruction.  There is the basic
  1098. MOVE that we have used up until now. This is used to move data around.  
  1099. MOVEA is used to move addresses. Example:    MOVEA    $5000,A0.
  1100. Yes - we should have been using this in the above examples when moving addresses into address
  1101. registers, but I wanted to show addressing types, not instruction types.  The Move Address is used
  1102. just like the Move command, but lets you know that it is an address that is being moved (which means
  1103. simply that the destination is an Address register).
  1104.  
  1105. MOVEQ    Move Quick:  A shortcut instruction that moves an eight bit signed integer into a data
  1106. register.
  1107. Two things to note:  1) a eight bit integer translates to -128 to +127 in decimal (the 8th bit is the
  1108. sign so we only get to use 7 bits as actual data), and 2) all 32 bits of the destination register are
  1109. affected.  This means that even though only 8 bits are used to represent the integer, these four bits
  1110. will be sign extended into a 32 bit integer (remember - sign extension means that the sign of the
  1111. number will be preserved as we use all 32 bits of the register).  Don't get too confused here.  The
  1112. MOVEQ instruction simply takes an 8 bit integer and turns it into a 32 bit integer before putting it
  1113. into a register.  We could certainly think of the eight bit integer as unsigned (always positive)
  1114. even though the instruction says that it is signed.  Signing the integer becomes important only when
  1115. we remember that the sign (or 8th bit) will be extended across 32 bits - so if you use MOVEQ to put
  1116. the unsigned number 255 (11111111 binary) into D0, the instruction says OK, here is the signed  eight
  1117. bit number -1 (in binary, -1 and 255 are the same), and it needs to be turned into a 32 bit signed
  1118. number.  Now we have problems with the 255 because -1 in 32 bits is 32 binary ones, but 255 in 32
  1119. bits is still only 8 binary ones.  This will make more sense when we look at data sizes.
  1120. This command is often used to load loop counters into D registers.  A standard MOVE instruction could
  1121. be used, but the MOVEQ is a shorter command and therefore takes up less memory and fewer machine
  1122. cycles.
  1123. Example:      MOVEQ    $50,D1    ;treat this instruction as a normal direct address MOVE.
  1124. MOVEM    Move Multiple: used to quickly move several registers to or from memory.
  1125.     Example:    MOVEM    D4-D7/A0-A5,$5000.
  1126. Moves data registers D4,D5,D6 and D7, and address registers A0,A1,A2,A3,A4, and A5 into memory
  1127. starting at $5000.  This command is used primarily at the start and end of subroutines to save the
  1128. contents of registers.  Note that by reversing the arguments (so that $5000 comes first), the
  1129. registers are restored to their original values which were saved in the above instruction.
  1130. There are a couple of other forms of the MOVE instruction, but they are rare and unimportant for
  1131. cracking.  If you see one, you should be able to figure out what it is doing.  Now, we look at
  1132. modifying the operands of the MOVE instruction.
  1133. Up until now, we have worked under the assumption that registers (and memory) contain 32 bits of
  1134. information.  This is not quite true.  First of all, a memory address can hold 8 bits of information. 
  1135. Luckily, the Mac is smart enough to know that if we are moving a 32 bit register into memory, it
  1136. needs to use 4 consecutive memory addresses.  Secondly, we aren't limited to just 32 bit
  1137. instructions.  Consider:
  1138. MOVE.L    D0,(A0)
  1139. MOVE.W    D0,(A0)
  1140. MOVE.B    D0,(A0)
  1141.  
  1142. These demonstrate the methods for referring to Long-words (all 32 bits), Words (16 bits) and Bytes (8
  1143. bits).  The first instruction moves all 32 bits of D0 into the address pointed to by A0.  Since the
  1144. address in A0 can hold only 8 bits of information, the processor will put the remaining 24 bits of
  1145. information into the three address following A0.  The second instruction says to move the low 16 bits
  1146. (I'll illustrate low bits in a second) into the address pointed to by A0 and the address following
  1147. A0.  The last instruction moves the low 8 bits of D0 into just the address pointed to by A0.
  1148.  
  1149. OK:  here is what all that really means.  Consider:
  1150.     Instruction    Memory Address Contents->    $5000    $5001    $5002    $5003
  1151.  
  1152.     MOVE    $5000,A0        ??    ??    ??    ??
  1153.     MOVE    $12345678,D0        ??    ??    ??    ??
  1154.     MOVE.B    D0,(A0)        $78    ??    ??    ??
  1155.     MOVE.W    D0,(A0)        $56    $78    ??    ??
  1156.     MOVE.L    D0,(A0)        $12    $34    $56    $78
  1157. Question marks indicate that the instruction did not affect that memory address.  Note that 1) when
  1158. the information to be moved is longer than 8 bits it is automatically moved into successive memory
  1159. addresses, and 2) the information is stored from most significant to least significant.  The terms
  1160. most and least significant (or high and low) are used to designate the higher vs lower portions of
  1161. the number.  In the number $1FF hex, the most significant byte is 01 and the least significant byte
  1162. is FF.  In the number $12345678, the MSB (most significant byte) is 12 and the LSB is 78.  In that
  1163. same number, the most significant word (2 bytes) is 1234 and the least significant word is 5678.  I
  1164. will often make references to both most/least significant bytes and most/least significant bits.  
  1165. One last thing before we move on is to note that when using the auto increment/decrment addressing
  1166. modes, the amount of increment or decrement is dependent upon the size of the data being moved (which
  1167. makes sense).  If you say MOVE.W  D0,(A0)+  then A0 will be incremented 2 bytes so that it then
  1168. points one address past the data just moved into it.  Likewise, if the instruction was MOVE.L 
  1169. D0,(A0)+, then A0 would be incremented by 4 bytes and would again point one address past the data
  1170. just moved.
  1171. Also, often the size identifier is left off the instruction (like in MOVE  D0,D2).  When this is the
  1172. case, it means the instruction is using a word size operand or MOVE.W.  If the instruction is
  1173. referring to byte or long-word size operands, it will explicitly say so in the command - MOVE.B or
  1174. MOVE.L.
  1175. Special Registers:
  1176. Program Counter, denoted PC.  This register always points to the instruction to be executed.  You
  1177. won't usually care what is contained in the PC, but you will want to do your assembly listings from
  1178. wherever it currently is.  TMON makes it very simple to start dis-assembling from the current PC so
  1179. that you can see on-screen the instructions that are going to be executed.
  1180. The Status Register:  very important.
  1181. This guy is how the processor keeps track of what just happened.  For example, anytime you compare
  1182. two values, you need to know if they were equal, not equal, one was bigger, etc.  All this type of
  1183. information is contained in the Status register.  Basically, the status register is a 16 bit register
  1184. in which certain bits contain information that you will want to access.  Don't worry about which bits
  1185. mean what  because assembly language has operators that refer to the bits with nice, easy to remember
  1186. mnemonics.  Here are the bits that you will care about:
  1187. Z    the zero flag.  This flag is set if the result of an operation is zero, or if two compared values
  1188. are the same - it is cleared otherwise.  For example, ADD.B  $FF,1 would result in the number $100. 
  1189. But since we specified a byte size operation, the byte result is 0 and the flag would be set.
  1190. C    the carry flag.  This contains the carry from an arithmetic operation.  If you add two 8 bit (.B)
  1191. numbers, the carry flag contains the 9th bit.  Say you add $FF and 1 again.  The result is a byte
  1192. valye of 0 with a carry into the next bit.  This carry would show up in the c flag.  This bit also
  1193. receives bits that are shifted out of a number during shift or rotate instructions.  (See commands
  1194. list).
  1195. N    the negative flag.  Set if the high bit (meaning the 8th bit when using the .B specifier, the
  1196. 16th bit for the .W, etc) of an operation gets set.   Also gets set if the result of an operation is
  1197. negative.
  1198. V    the overflow flag.  Set whenever an operation yields a result that cannot be properly
  1199. represented.  For example, when adding the bytes 7F and 01, the result  - 80 - cannot be represented
  1200. in 8 bits.  In eight bits, the eighth bit is the sign bit (telling whether the number is posative or
  1201. negative).  Note that this only happens if you are adding bytes - if the command added words, then
  1202. the result CAN be represented in 16 bits.  This flag won't be used too much.
  1203. X    the extended flag.  This is basically a copy of the carry bit, but not all operations affect it. 
  1204. The X flag is used to enable multi-precision instructions, that is, instructions can be intermixed
  1205. without always affecting the X flag (in this case , the multi-precision carry bit).  Once again, not
  1206. used to much.
  1207. This probably doesn't make too much sense.  That's OK, because you will get the hang of it when we
  1208. look at a batch of code listings.  The only reason I am listing them here is because TMON can display
  1209. these flags and their current values.  This allows you to predict where the program is going when it
  1210. decides to branch somewhere.  These flags are used to control program flow and, as such, are the
  1211. single most important element to cracking.  This is how you tell a program that the password you just
  1212. typed was equal (and not unequal) to the password the program is looking for.  We will look at the
  1213. branch instructions later on.  These instructions almost all use the Status Register Flags.
  1214. The final special register is actually just the A7 address register.  The reason it is special  is
  1215. because it is used as the stack pointer on the Mac.  The Stack is basically a chunk of memory that is
  1216. used for special situations such as jumping to a subroutine and having to remember where the program
  1217. jumped from so it can return when the subroutine is finished.  The stack is also an excellent way to
  1218. pass values to a subroutine.  This will be illustrated later.  All you need to understand is that the
  1219. Stack is a piece of memory and can be manipulated as such.  To refer to the stack, refer to the A7
  1220. register.  Also, the stack moves backwards as it is used.  Therefore, when a program wants to put a
  1221. number on the stack it uses the pre-decrement indirect addressing mode:
  1222.     MOVE    D0,-(A7)    ;puts the value in D0 onto the stack and moves the stack pointer back one
  1223. address.
  1224.     MOVE    (A7)+,D0    ;puts the value on the stack into D0 and increments the stack pointer to the
  1225. next stack value.
  1226. And of course, to get the value back off the stack, you would use Post-Increment.  These are not
  1227. always used, but when they are used, it moves the stack pointer to the next available piece of stack
  1228. space.  When we begin working with Traps, you get a good workout with the stack so don't worry if
  1229. this doesn't make complete (or any) sense yet.
  1230. Traps
  1231. Traps are a quick and easy method of accessing the 9 jillion built-in subroutines found in the
  1232. Macintosh ROM.  Traps do everything under the sun and are probably the main reason that all the Mac
  1233. programs look alike.  When a program wants do anything from drawing text to bringing up dialog boxes
  1234. to putting up menus, traps are used.  Why not just call the subroutines directly?  Well, the problem
  1235. is that every time Apple comes out with new system software, they change the addresses of one or more
  1236. of these subroutines that almost all programs need.  This would create chaos for applications, so
  1237. Apple uses the idea of a trap table.  The trap table is a means of associating the trap name
  1238. (actually it's machine language code) with the proper address of the subroutine.  So, no matter what
  1239. the system version (within reason), an application can use the trap table to correctly call the
  1240. subroutine it wants.  These traps are easy to spot: they all start with an underscore and then the
  1241. name of the trap, e.g. _GetNewDialog.
  1242. A quick note about traps and viruses / anti-virus programs.  If you were ever wondering how a virus
  1243. program works, consider that a virus needs to be able to write portions of itself onto a disk.  To do
  1244. this, it needs to have access to an operating system that can do the actually writing.  It could
  1245. either pack an operating system around with itself (unwieldy and difficult to change when apple
  1246. modifies the system) or use the trap table to call the traps that write resources.  Now, the trap
  1247. table can be patched by a program...i.e. a programmer can substitute his own subroutine into the trap
  1248. table so that any program that calls the trap to do something, actually calls the new subroutine. 
  1249. Knowing this, an application could be written that patches the trap table and monitors the activity
  1250. of any trap that writes resources.  (I haven't de-compiled the newer virus programs, but I know
  1251. that's how vaccine worked).  The anti-viral program then just sits back and intercepts any of these
  1252. traps, takes a look to see just what it is that is being written and where.  If it looks suspicious
  1253. (like writing an nVIR resource to the system!) then it lets you know.  WDEF was a really great virus
  1254. because the programmer figured a way to bypass this method.  The first thing WDEF does is try to
  1255. determine exactly which system it is operating under, and, if it is one that it recognizes (the 6.0x
  1256. series I believe) it will re-patch the trap table with the original system values so that it can
  1257. write to the disk without being monitored!  The key is that this only works if WDEF knows the
  1258. original values of the trap table and, since they often change, this means that WDEF is only
  1259. effective on certain system versions.  (Note that if it cannot re-patch the trap table, it will
  1260. attempt to run and hope that there is no anti-virus program running).
  1261. Well, back to assembly.  Almost every trap needs some parameters to operate.  For example,
  1262. GetNewDialog needs several parameters, including the ID # of the dialog to load, and several other
  1263. things; and it returns a pointer to the dialog.  Here is where the stack becomes important.  Most
  1264. traps use the stack to pass parameters and return values.  Consider the following code (which will
  1265. probably be incomprehensible)
  1266.  
  1267.     CLR    -(A7)    ;put 0 (word length since there is no size specifier ) on the stack
  1268.     MOVE    $2FF,-(A7)    ;Put $2FF (word size again) on the stack.
  1269.     CLR.L    -(A7)    ;put a nil-pointer on stack
  1270.     _StopAlert    
  1271.     MOVE    (A7)+,D0
  1272.  
  1273. This little subprogram brings up an alert dialog.  If we were to look in Inside Mac vol 1under
  1274. StopAlert we would find that it requires 2 arguments and returns one result.  If we were programming,
  1275. we would care what types of information these parameters are (integer, pointer, etc.) but since we
  1276. are cracking, we can assume that the program to be cracked has already figured all this out.  
  1277. Anytime a trap returns a value the calling code must allocate space on the stack before it puts the
  1278. parameters on the stack.  That is precisely what the CLR instruction does. (CLR or clear, puts zero
  1279. into its operand so CLR.L   D0 would put 32 zero bits in D0)  This is a fast way to move the stack
  1280. pointer back one byte...we don't actually care what get puts on the stack (zero in this case) because
  1281. the trap is going to replace that number with its return result.  Since Inside Mac says StopAlert
  1282. returns an integer and that an integer is 2 bytes or 1 word, we first clear an integer's worth of
  1283. space on the stack.
  1284. Next we start putting arguments on the stack in the same order as Inside Mac says.  The first thing
  1285. is the alertID which is an integer.  This is simply the number of the alert - i.e. the number you
  1286. would see if you looked at the alerts in Resedit.  So, this number ($2FF in my example) is moved onto
  1287. the stack.  The second argument is filterproc and is a procpointer (nothing more than a pointer). 
  1288. This argument is used only if the built-in dialog handlers don't quite cut it for you're application
  1289. (maybe you have special command keys to watch for or something).  If this is the case, you would pass
  1290. a pointer to you're filtering procedure in this argument.  Since I don't care about this, I will pass
  1291. a nil pointer (one that points to nothing - this is defined as $00000000 [a long word] in assembly).
  1292. Once I have put the proper information on the stack, I can call the trap.  The final instruction
  1293. moves the trap result from the stack into register D0.  At this point I can test the result and
  1294. branch accordingly. 
  1295.  
  1296. Finally, let's take at the branching structures.  Branching is how a program makes decisions based
  1297. upon tested values.  For example, you type in a password. The program must compare what you typed in
  1298. with what the true password is.  Once it compares the two, it has to be able to go one place if you
  1299. typed in the correct value, and someplace else if you typed in the wrong password.  There are several
  1300. ways to compare values, and I will cover all of them in a listing of the assembly commands.  The most
  1301. common is the CMP (compare) command.  This compares its two operands, and sets the Z flag if the two
  1302. are equal and clears the Z flag if the the two are different.  Don't worry if the Z-flag doesn't
  1303. quite register - it was one of the bits of the status register and you won't care too much about
  1304. it...just note that the various branching instructions will be testing the status flags and jumping
  1305. to a new chunk of the program accordingly.  How about an example?
  1306.     
  1307.     MOVE.B    1,D0
  1308.     MOVE.B    2,D1
  1309.     CMP.B    D0,D1
  1310.     BEQ    Code Section 1
  1311.     BNE    Code Section 2
  1312. OK, first we move two numbers into D0 and D1.  The CMP instructiion compares the two values (actually
  1313. it subtracts the second from the first - thus you can test for more things than just the two being
  1314. equal) and sets the status register accordingly.  From this example, we can see the the two are not
  1315. equal and so the BEQ (branch if equal) will not be executed.  However the BNE (branch if not equal)
  1316. will be executed since the values are indeed not equal.  The branch instructions cause program
  1317. execution to actually jump to a new spot in memory.  From this example, you can see that what flags
  1318. in the status register actually get set is not of primary concern.  All you have to know is that two
  1319. values are being compared, and the program wants to know if they are equal - as opposed to wanting to
  1320. see which was bigger...consider:
  1321.     
  1322.     MOVE.B    1,D0
  1323.     MOVE.B    2,D1
  1324.     CMP.B    D0,D1
  1325.     BGT    Code Section 1
  1326.     BLE    Code section
  1327. Here, the program wants to know which value is bigger.  In this example, if D1 is bigger than D0, the
  1328. the BGT (branch if greater than) will execute.  The BLE (branch is less than or equal) will not
  1329. execute.  This is really easy to pick out in programs - as long as one of the various CMP
  1330. instructions is used...note I say of the various; remember that most commands have several modes:
  1331. consider CMP (compare), CMPA (compare address), CMPI (compare immediate), CMPM (compare memory). 
  1332. Once again, you don't care which of these is being used, you just care what the hell is being
  1333. compared, and how they are being compared (are they equal?, is one bigger?, etc)
  1334. Let me quickly mention that BEQ is not technically branch if equal (although functionally it
  1335. certainly is).  BEQ means branch if equal to zero (referring to the Z bit in the status register) and
  1336. BNE means branch if not equal to zero.  This is not critical, but it will help you to correlate the
  1337. zero bit in the status register with the BEQ and BNE instructions.
  1338. OK, now let's take this one step further.  You know that a program can use the CMP instruction to
  1339. test two values and you know that something happens to the status register - but you really don't
  1340. care what - and you also know that you can jump to a new section of code based upon the result of the
  1341. CMP.  Consider for a moment the fact that the branch instructions depend entirely upon a bit in the
  1342. status register.  By this I mean that BEQ only executes if the Z (zero) bit is set, BCC (branch carry
  1343. clear) only executes if the carry flag is clear, etc.  From this it should be evident that ANY
  1344. operation that changes the status register bits, could potentially be a reference for a branch. 
  1345. Consider the seemingly harmless enough CLR instruction.  It serves to put the value zero into its
  1346. operand.  But, by its very definition, the CLR instruction sets the Z flag to 1 since it is setting
  1347. something equal to zero.  There are a slew of commands that set and clear the various bits in the
  1348. status register.  Refer to the command listing to see which commands affect which status flags.
  1349.  
  1350. There are also several ways to change which section of code is currently executing.  As you have
  1351. seen, the branch instructions all cause the program to jump to another piece of code.  Similarly, the
  1352. BRA (branch with no test of status flags), JMP (jump), BSR (branch to subroutine) and JSR (jump to
  1353. subroutine) all cause the program to jump to another location and begin executing.  The BSR and JSR
  1354. will cause the program to execute at its new loaction until an RTS (return from subroutine) is
  1355. encountered at which point the program jumps back to the instruction following the original JSR or
  1356. BSR.
  1357. Finally, I want to quickly discuss two important instructions: PEA and LEA, which stand for Push
  1358. effective address and Load effective address.  Basically, LEA takes the first argument, computes the
  1359. address at which that argument resides, and puts that address into the second argument.  PEA computes
  1360. the address of the argument and puts that address onto the stack.  Many programs use PEA as a
  1361. shortcut to putting trap arguments onto the stack. For example:
  1362.     
  1363.     LEA    var1,A0    ;put the address of variable 1 into A0
  1364.     MOVEA.L    A0,-(A7)    ;put address on stack.
  1365.     
  1366.     PEA    var1    ;put address of variable1 on the stack.
  1367. These two code listings do essentially the same thing.  The first computes the address where variable
  1368. 1 resides in memory and places that address in A0.  At this point, we could use A0 to move
  1369. information into an out of the variable var1 using indirect addressing (MOVE    1,(A0)).  Then, the
  1370. address in A0 is placed on the stack.  The last line directly moves the address of variable onto the
  1371. stack accomplishing the same thing as the previous instructions.
  1372. A word about pointers and handles.  You should be familiar with pointers by now.  A pointer is simply
  1373. an address which is used to access the memory that it points to.  A handle is nothing more than a
  1374. pointer to a pointer.  That is, a handle is an address that points to some piece of memory, just like
  1375. a pointer.  The difference is that the memory the handle points to contains the address of yet
  1376. another piece of memory.  Many traps return handles to data rather than pointers.  The reason is so
  1377. that if the Mac's memory manager needs to move memory around, pointers can be moved without loosing
  1378. the handle to the pointer.  This isn't too important to cracking since, once again, the program knows
  1379. how to handle its pointers.  You will often find a section of code that looks like this:
  1380.  
  1381.     _GetNewDialog    ;this trap returns a handle (according to IM) to the dialog in question.
  1382.     MOVE.L    (A7)+,A0    ;Move the handle from the stack into A0.
  1383.     MOVE.L    (A0),A0    ;A0 now contains the pointer.
  1384. Basically, this turns a handle into a pointer.  First, the handle is moved from the stack into A0. 
  1385. (Remember, traps pass return values via the stack).  Next, using indirect addressing, the handle is
  1386. turned into a pointer.  The last line first looks at the value in A0 and treats it as an address. 
  1387. Then it looks at the contents of this address.  This 32 bit value (which is actually the pointer that
  1388. the handle points to) is then moved back into  A0.  Lets say A0 contains memory address 1000.  At
  1389. memory address 1000 is the value 2000.  Now, 2000 is where the data we care about is actually
  1390. located.  So, we take the value in 1000 (which is 2000) and place that value back into A0.  After
  1391. this line, A0 contains the value (or address) 2000 and so A0 points to the data in question.  I
  1392. illustrate this because it is an often used technique.
  1393. Following is a detailed description of all the 68000 instructions.  Some day I will buy a book on
  1394. 68030/68882 instructions and update this, but it should serve for now.
  1395.  
  1396. COMMAND LISTING
  1397. ABCD    Add Binary Coded Decimal.  Add two operands using BCD, result is in the second operand. 
  1398. Binary coded decimal is basically hexidecimal without the letter codes for the numbers 10-15.  Using
  1399. this, we get the flexibility of hexidecimal but the convience of decimal.  I have yet to see this
  1400. used. Flags affected:
  1401.     N:    Undefined.
  1402.     Z    Cleared if the result is not zero, otherwise unchanged.
  1403.     C    Set by carry out of the most significant BCD digit.
  1404.     X    Same as C.
  1405.     V    Undefined.
  1406.  
  1407. ADD    Add two operands, result in the second operand. Flags affected:
  1408.     
  1409.     N    Set if high-order bit of result was 1, otherwise cleared.
  1410.     Z    Set if result was zero, cleared otherwise.
  1411.     C    Set by the carry out of the most significant bit, cleared otherwise.
  1412.     X    Same as C.
  1413.     V    Set if operation results in an overflow (see definition of this bit).
  1414.  
  1415. ADDA    Add Address: add the contents of address registers, result in second operand.  Flags
  1416. affected: None
  1417.  
  1418. ADDI    Add Immediate:  Add a constant to an effective address, result in second operand.  Flags
  1419. affected:
  1420.  
  1421.     N    Set if high bit of result is set.
  1422.     Z    Set result is zero.
  1423.     C    Set on carry out of most significant bit.
  1424.     X    Same as C.
  1425.     V    Set on overflow.
  1426.  
  1427. ADDQ    Add Quick:  Add a three bit value to the second argument, result in second argument.  Flags
  1428. affected:
  1429.  
  1430.     N    Set if high bit of result is set.
  1431.     Z    Set if result is zero.
  1432.     C    Set of carry out of high bit.
  1433.     X    Same as C.
  1434.     V    Set on overflow.
  1435.  
  1436. ADDX    Add Extended:  add two values but allowing for values that require more than 32 bits of
  1437. information.  Flags affected:
  1438.  
  1439.     N    Set result was negative.
  1440.     Z    Cleared if result is not zero. Else unchanged.
  1441.     C    Set on carry out of high bit.
  1442.     X    Same as C.
  1443.     V    Set on overflow.
  1444.  
  1445.  
  1446. AND    Performs bit-wise and upon the two operands with the result in the second operand.  This means
  1447. that the two values are compared bit by bit.  For every binary digit, if both operands contain a one,
  1448. the result will contain a 1, otherwise the result will contain a zero.  For example, consider 101 AND
  1449. 110.  The result would be 100 (only the third bit is set in both numbers. Flags affected:
  1450.  
  1451.     N    Set if high bit of result is set.
  1452.     Z    Set if result is zero, cleared otherwise.
  1453.     C    Always cleared.
  1454.     V    Always cleared.
  1455.  
  1456. ANDI    And Immediate: Performs bitwise and with a constand and an operand, result in second operand. 
  1457. Flags affected: same as AND instruction
  1458.  
  1459. ASL    Arithmetic Shift Left:  Performs a bitwise shift left.  If there are two arguments, then the
  1460. first determines how may times to shift the bits to the left.  The lowest bit is set to zero.
  1461.  
  1462.     X    Set according to the last bit shifted out of the operand (that is, the most significant bit
  1463. before the shift was executed.
  1464.     N    Set according to the most significant bit in the result.
  1465.     Z    Set if the result is equal to zero (all bits zeroed), cleared otherwise.
  1466.     C    Same as the X bit.
  1467.     V    Set if the most significant bit is changed at any time during the operation. (That is, if the
  1468. ASL involves shifting more than one time, then if during any of the shifts, the msb is changed, V is
  1469. set).  NOTE - the msb does NOT mean the leftmost bit as I described way back when.  It DOES mean the
  1470. leftmost bit within the range of the operation.  In other words, if it is a byte level shift, then
  1471. the 8th bit is the msb, if the operation is at the word level, the the 16th bit is the msb, etc.
  1472.  
  1473. A quick note about bit operations is probably in order.  Basically, any register contains 32 bits,
  1474. each of which is either a one or a zero.  Assembly language contains several commands for directly
  1475. manipulating the individual bits in a register - as opposed to manipulating the entire value
  1476. contained in the register.  For example, consider the ASL above.  Basically, this command moves each
  1477. bit in the register in question over one slot.  Now, knowing how binary numbers work, you should be
  1478. able to see that this operation serves to effectively multiply the value of the entire register by 2. 
  1479. Similarly, the ASR (shift right) will effectively divide the value in the register by 2.  There are
  1480. also commands to set and clear individual bits, as well as test to see if individual bits are set. 
  1481. More on these commands later in the listing...
  1482.  
  1483. ASR    Arithmetic Shift Right:  Performs a bitwise shift right.  If there are two arguments, then the
  1484. first determines how may times to shift the bits to the right.  The most significant bit is unchanged
  1485. (and not zeroed as in the ASL); this is so that the sign bit remains unchanged.
  1486.  
  1487.     X    Set according to the last bit shifted out of the operand (that is, the lowest bit before the
  1488. shift was executed.
  1489.     N    Set according to the most significant bit in the result.
  1490.     Z    Set if the result is equal to zero (all bits zeroed), cleared otherwise.
  1491.     C    Same as the X bit.
  1492.     V    Always cleared.
  1493.  
  1494.  
  1495. OK, next are the infamous branch instructions.  Basically, all these operations will examine one or
  1496. more of the flags and jump to a new section of code based on the result.  None of these affect the
  1497. status flags.  Since these are the instructions that usually need to be altered to crack a program, I
  1498. will list the actual hex codes associated with the instructions.  This way you can go into Resedit
  1499. and apply the patch.  All the branches translate to 6X AA in hex where X is the status flag to check,
  1500. and AA is the address to branch to.  To modify the type of branch, just change the X, e.g. to change
  1501. BEQ (67 hex) into BNE (66 hex) just go into Resedit, find the 67 in question, and replace it with 66. 
  1502. To change the address that the branch jumps to, you need to find the address you want the branch to
  1503. jump to.  Then start counting instructon bytes starting with the byte immediately following the
  1504. branch instruction.  Call that byte zero and count upwards to the spot to jump to.  This number (the
  1505. difference between the two addresses is the AA parameter.  Note that you can start counting backwards
  1506. also if you need to branch backwards.  More on all of this in the actual cracking manual.  Here they
  1507. are:
  1508.  
  1509. BCC    Branch Carry Clear.  Branch if the C flag is clear.  64 hex.
  1510.  
  1511. BCS    Branch Carry Set.  Branch if the C flag is set.  65 hex.
  1512.  
  1513. BEQ    Branch if Equal.  Branch if the Z flag is set.  67 hex.
  1514.  
  1515. BNE    Branch if Not-Equal.  Branch if the Z flag is clear.  66 hex.
  1516.  
  1517. BGE    Branch if Greater Than or Equal.  Branch if the N and V flags are either both set or both
  1518. cleared.  Basically, when dealing with these multi-flag branches (yes, there are several more coming
  1519. up), look at the instruction that set the flags (usually a CMP) and ask yourself whether the
  1520. relationship between the 2nd and 1st operands (the order is critical!) is true.  So, for BGE, look at
  1521. the CMP and say  - is the 2nd operand greater than or equal to the first?  If so, the branch will go. 
  1522. Or you can just step through this stupid command with TMON and see whether or not it branches.  6C
  1523. hex.
  1524.  
  1525. BGT    Branch if Greater Than.  Branch if 1) N and V are set and Z is clear, or 2) N, V, and Z are all
  1526. clear.  Basically the same as above but don't branch if the two are equal.  6E hex.
  1527.  
  1528. BLE    Branch if Less Than or Equal.  Branch if 1) the Z bit is clear, 2) N is set and V is clear, or 3)
  1529. N is clear and V is set.  6F hex.
  1530.  
  1531. BLT    Branch if Less Than.  Branch if 1) N is set and V is clear, or 2) N is clear and V is set.  6D
  1532. hex.
  1533.  
  1534. BHI    Branch if Higher Than.  Branch if C and Z are both clear.  Treat this as the same as BGT.  62
  1535. hex.
  1536.  
  1537. BLS    Branch if Lower or Same.  Branch if either C or Z are set.  Treat this as BLE.  63 hex.
  1538.  
  1539. BMI    Branch Minus.  Branch if the N bit is set.  6B hex.
  1540.  
  1541. BPL    Branch Plus.  Branch if the N bit is clear.  6A hex.
  1542.  
  1543. BVC    Branch V Clear.  Branch if V is clear.  68 hex.
  1544.  
  1545. BVS    Branch V Set.  Branch if V is set.  69 hex.
  1546.  
  1547. BRA    Branch.  Branch regardless of what the hell is in the flags.  This one is important...Imagine a
  1548. program checking for an original disk, and then saying BEQ to the rest of the program.  If Z is
  1549. clear, the program continues and bombs.  Now imagine changing that BEQ to BRA.  All of a sudden, the
  1550. dumb thing jumps to itself correctly no matter what happens!  60 hex.
  1551. BCHG    Bit test and Change.  Inverts the nth bit (determined by the first operand) in the 2nd
  1552. operand.  Z is set according to the state of the bit BEFORE the inversion (by this I mean that if the
  1553. bit was 0, Z is set and vice versa).  No other flags are changed.
  1554.  
  1555. BCLR    Bit test and Clear.  Same as above but clears the nth bit instead of inverting it.  Flags are
  1556. set the same.
  1557.  
  1558. BSET    Bit test and Set.  Same as BCLR but sets the nth bit instead of clearing it.  Flags are set
  1559. the same.
  1560.  
  1561. BSR    Branch to Subroutine.  This instruction first places the instruction following the BSR onto the
  1562. stack.  Next, operation is continued at the address specified by the BSR - called a subroutine.  At
  1563. the end of the subroutine will be a return instruction - covered later - at which point the original
  1564. address is popped off the stack and execution continues from the instruction following the BSR.  BSR
  1565. is the same as JSR for all intents and purposes, except that BSR can first check any of the status
  1566. flags the same way that the branch instructions did.
  1567.  
  1568. BTST    Bit Test.  Test the nth bit of an operand and set the Z flag accordingly.
  1569.  
  1570. CLR    Clear.  Sets its operand to zero.
  1571.  
  1572.     N    Always cleared.
  1573.     Z    Always set.
  1574.  
  1575. CMP    Compare.  Compares two values.  Actually, this command sets the status flags as if the second
  1576. operand were subtracted from the first (but  neither operand is actually changed).  See the SUB
  1577. command for more details.
  1578.  
  1579.     N    Set if the result is negative.  Cleared otherwise.
  1580.     Z    Set if the result is zero - or if the operands are equal. Cleared otherwise.
  1581.     C    Set if the result generates a borrow.  Cleared otherwise.
  1582.     V    Set on overflow in the subtract.  Cleared otherwise.
  1583.  
  1584. CMPA    Compare Address.  Same as above but this command will be used to compare address registers.
  1585.  
  1586. CMPI    Compare Immediate.  Same as CMP, but this command will be used if the first operand is an
  1587. actual number (instead of a register).
  1588.  
  1589. CMPM    Compare Memory.  Once again, same as CMP, but this command always uses post-increment
  1590. addressing and compares two memory addresses.
  1591.  
  1592. Decrement and Branch instructions
  1593. These commands make up part of assembly language's looping structures.  Essentially, these commands
  1594. decrement a loop counter (a specified data register) and branch back to the start of the loop.  There
  1595. are two ways that the loop may be terminated.  First, if the condition is met, the loop will end, and
  1596. second, if the loop counter reaches -1 then the loop will end.  I am not going to list all the
  1597. conditions for each command - for these, refer to the corresponding branch instruction.
  1598.  
  1599. DBRA    Decrement and Branch.  No conditions are checked - terminate loop only when the loop counter
  1600. reaches -1.
  1601.  
  1602. DBCC    Decrement and Branch unless Carry Clear.
  1603. DBCS    Decrement and Branch unless Carry Set.
  1604.  
  1605. DBEQ    Decrement and Branch unless Zero.
  1606.  
  1607. DBNE    Decrement and Branch unless Not Zero.
  1608.  
  1609. DBGE    Decrement and Branch unless Greater Than or Equal.
  1610.  
  1611. DBGT    Decrement and Branch unless Greater Than.
  1612.  
  1613. DBHI    Decrement and Branch unless Higher Than.
  1614.  
  1615. DBLE    Decrement and Branch unless Less Than or Equal.
  1616.  
  1617. DBLS    Decrement and Branch unless Less Than or Same.
  1618.  
  1619. DBLT    Decrement and Branch unless Less Than,
  1620.  
  1621. DBMI    Decrement and Branch unless Minus.
  1622.  
  1623. DBPL    Decrement and Branch unless Plus.
  1624.  
  1625. DBVC    Decrement and Branch unless V Clear.
  1626.  
  1627. DBVS    Decrement and Branch unless V Set.
  1628.  
  1629.  
  1630. DIVS    Divide Signed.  Divides a 32 bit quantity (second operand) by a 16 bit quantity (first
  1631. operand).  The low order word of the 2nd operand gets the quotient and the upper word gets the
  1632. remainder.
  1633.  
  1634.     N    Set if quotient is negative cleared otherwise.  Undefined if overflow.
  1635.     Z    Set if result is zero, cleared otherwise.  Undefined if overflow.
  1636.     C    Always cleared.
  1637.     V    Set on overflow.
  1638.  
  1639. DIVU    Divide Unsigned.  Treat this as identical to the above instruction except that the result is
  1640. treated as an unsigned integer.  Flags are set the same.
  1641.  
  1642. EOR    Exclusive Or.  Performs an exclusive or (which means that each bits are compared, if both are 1,
  1643. the resultant bit is 0, if one of the two is 1, the result is 1, and if both are 0, the result is 0)
  1644. on two operands.  The result is in the 2nd operand.  Example: EOR  1010,0011 (both binary) would
  1645. yield 1001.  This is not a valid instruction, but does show how exclusive or works.
  1646.  
  1647.     N    Set if the most significant bit of the result is 1, cleared otherwise.
  1648.     Z    Set if the entire result is zero (all bits zero), cleared otherwise.
  1649.     C    Always cleared.
  1650.     V    Always cleared.
  1651.  
  1652. EORI    Exclusive Or Immediate.  Same as above, but the first operand will be an actual number.
  1653.  
  1654. EXG    Exchange.  Exchanges all 32 bits of any two registers.  No flags are affected.
  1655.  
  1656. EXT    Extend.  Extends the sign bit into either a word or long word data size.
  1657.  
  1658.     N    Set if result is negative, cleared otherwise.
  1659.     Z    Set if result is zero, cleared otherwise.
  1660.     C    Always cleared.
  1661.     V    Always cleared.
  1662.  
  1663. JMP    Jump.  Transfers control to another section of code.  The address supplied (using any of the
  1664. addressing modes) is put into the program counter and execution commences from that address.  No
  1665. flags are affected.
  1666.  
  1667. JSR    Jump Subroutine.  Places the address of the next instruction on the stack, places the supplied
  1668. address in the PC, and commences execution at the supplied address.  When the subroutine executes a
  1669. return instruction (below) the address on the stack is popped off and placed in the PC and execution
  1670. commences at the address following the JSR.  No flags are affected.
  1671.  
  1672. LEA    Load Effective Address.  Computes the address of the first operand and places that address in the
  1673. 2nd operand.  No flags are affected.
  1674.  
  1675. LINK    Link.  This command is a bitch to understand, but it is used a lot and is the method most
  1676. compilers use to handle local variables for subroutines.  Basically, Link creates what is called a
  1677. Stack Frame on the Stack.  Link takes two operands, an address register (A6 is almost always used),
  1678. and the size of the stack frame to create.  First, the address register is pushed on the stack and
  1679. the resulting stack pointer is placed in the address register making it a new temporary stack
  1680. pointer.  Then the 2nd argument is added (note that this number is usually negative) to the original
  1681. stack pointer.  The memory between the stack pointer and the address register is then treated as a
  1682. buffer to contain any local variables the subroutine may need.  Don't worry to much about the
  1683. dynamics of this command - just remember that usually, a subroutine will start with a LINK command,
  1684. and end with an Unlink command and then return to the calling procedure.
  1685.  
  1686. LSL    Logical Shift Left.  Performs a bitwise left shift on the second operand (or the first if there
  1687. is only one).  The first operand (if there are two) tells how many times to shift.  The first bit is
  1688. set to zero.
  1689.  
  1690.     X    Set according to the most significant bit before the shift is executed.
  1691.     N    Set a one is shifted into the most significant bit (indicating a negative result for signed
  1692. numbers), cleared otherwise.
  1693.     Z    Set if the entire result is zero, cleared otherwise.
  1694.     C    Same as X.
  1695.     V    Always cleared.
  1696.  
  1697. LSR    Logical Shift Right.  Same as above, but shifts right.  The most significant bit is set to zero
  1698. (meaning the sign is lost.  If this important, the program would use ASR instead).
  1699.  
  1700.     X    Set according to the first bit before the shift was executed.
  1701.     N    Always cleared (since zero is shifted into the sign bit).
  1702.     Z    Set if the result is zero, cleared otherwise.
  1703.     C    Same as X.
  1704.     V    Always cleared.
  1705.  
  1706.  
  1707. MOVE    Move.  Moves the first operand into the second operand.
  1708.  
  1709.     N    Set if the most significant bit of the result is set, cleared otherwise.
  1710.     Z    Set if the result is zero, cleared otherwise.
  1711.     V    Always cleared.
  1712.     C    Always cleared.
  1713.  
  1714. MOVEA    Move Address.  Same as Move except that address regesters are being used.  No flags are
  1715. affected.
  1716.  
  1717. MOVEM    Move Multiple.  Moves the specified register(s) onto or out of the stack to facilitate
  1718. temporary storing of the registers.
  1719.  
  1720. MOVEQ    Move Quick.  Moves an 8 bit signed integer into a register.  The 8 bit integer is sign
  1721. extended to 32 bits and then all 32 bits are placed into the destination register.
  1722.  
  1723.     N    Set if result is negative, cleared otherwise.
  1724.     Z    Set if result is zero, cleared otherwise.
  1725.     C    Always cleared.
  1726.     V    Always cleared.
  1727.  
  1728. MULS    Multiply Signed.  Multiplys the first argument by the second with the result in the second
  1729. operand.
  1730.  
  1731.     N    Set if the result is negative, cleared otherwise.
  1732.     Z    Set if the result is zero, cleared otherwise.
  1733.     C    Always cleared.
  1734.     V    Always cleared.
  1735.  
  1736. MULU    Multiply Signed.  Same as above.  I am not sure as to the exact difference between the two
  1737. multiply command nor the two divide commands.  I wouldn't worry about it.
  1738.  
  1739. NBCD    Negate Binary Coded Decimal.  Converts a BCD number into its corresponding negative value,
  1740. much the same as the NEG instruction (below).
  1741.  
  1742. NEG    Negative.  Performs two's complement on the supplied operand converting it to its negative
  1743. counterpart.
  1744.  
  1745.     X    Cleared if the result is zero.  Set otherwise.
  1746.     N    Set if the result is negative.  Cleared otherwise.
  1747.     Z    Set if the result is zero.  Cleared otherwise.
  1748.     V    Set on overflow.  cleared otherwise.
  1749.     C    Same as X.
  1750.  
  1751. NEGX    Negative Extended.  Same as NEG but used for multi-precision numbers.
  1752.  
  1753.     X    Set on borrow.  Cleared otherwise.
  1754.     N    Set if result is negative.  Cleared otherwise.
  1755.     Z    Cleared if result is not zero.  Otherwise unchanged.
  1756.     V    Set on overflow.  Cleared otherwise.
  1757.     C    Same as X.
  1758.  
  1759.  
  1760. NOP    No Operation.  A two byte instruction that does nothing.  This is supposedly to allow programmers
  1761. room for future expansion or something, but I suspect it is to allow crackers to remove instructions
  1762. without fouling up the program.  No flags are affected.  The hex code is 4E71 and we will definately
  1763. be using this to effectively remove offensive instructions from applications - note that it is a 2
  1764. byte instruction, the same size as a branch instruction...
  1765.  
  1766. NOT    One's Complement.  Inverts every bit in the operand.
  1767.  
  1768.     N    Set if result is negative.  Cleared otherwise.
  1769.     Z    Set if zero.  Cleared otherwise.
  1770.     V    Always cleared.
  1771.     C    Always cleared.
  1772.  
  1773. OR    Binary OR.  Compares bits one at a time from the two operands.  Result bit is one unless both
  1774. bits are zero.  Result bits into second operand.  Example:  OR  0101,1100 yields 1101.
  1775.  
  1776.     N    Set if most significant bit of the result is set, cleared otherwise.
  1777.     Z    Set if result is zero, cleared otherwise.
  1778.     V    Always cleared.
  1779.     C    Always cleared.
  1780.  
  1781. ORI    OR Immediate.  Same as OR but used when the first operand is a numeric constant.  Same flags set
  1782. as OR.
  1783.  
  1784. PEA    Push Effective Address.  Pushes the address of the supplied operand onto the stack using auto
  1785. post-decrement.  This command is often used to pass pointers (VAR variables in Inside Mac) to traps
  1786. and subroutines.  No flags affected.
  1787.  
  1788. ROL    Rotate Left.  Similar to the Left Shifts, except that not only is the leftmost bit shifted into
  1789. the C flag, but it is also rotated back into the first bit of the operand (instead of a zero being
  1790. shifted there).
  1791.  
  1792.     N    Set if one is rotated into the most significant bit, cleared otherwise.
  1793.     Z    Set if result is zero, cleared otherwise.
  1794.     C    Set according to the last bit shifted out of the operand.
  1795.     V    Always cleared.
  1796.  
  1797. ROR    Rotate Right.  Same as ROL, but shift to the right.  The bit shifted out of the lowest position
  1798. is placed into the C flag, and also rotated back into the most significant bit.
  1799.  
  1800.     N    Set if one is rotated into the msb, cleared otherwise.
  1801.     Z    Set if the result is zero, cleared otherwise.
  1802.     C    Set according to the last bit shifted out of the operand.
  1803.     V    Always cleared.
  1804.  
  1805. ROXL    Rotate Left with Extend.  Same as ROL, but the bit that gets shifted into the C flag is also
  1806. shifted into the X flag.  Flags identical to ROL except that the X flag will be the same as the C
  1807. flag.
  1808.  
  1809. ROXR    Rotate Right with Extend.  Same as ROR, but the bit that gets shifted into the C flag is also
  1810. shifted into the X flag.  flags identical to ROR except the the X flag will be the same as the C
  1811. flag.
  1812.  
  1813.  
  1814. RTS    Return from Subroutine.  Places the long word from the top of the stack into the program counter
  1815. and resumes execution.  This has the effect of returning execution at the end of a subroutine called
  1816. with either BSR or JSR.  No flags are affected.
  1817.  
  1818. Set Instructions.  This is a group of instructions that use the condition flags in an identical
  1819. manner to the Branch instructions and therefore will not be listed out in full detail.  Essentially,
  1820. if the condition that the command is testing (for example, not equal) then the operand's low byte is
  1821. set to all ones (hex FF), otherwise the byte is cleared to zero.  Example:
  1822. SEQ    D0    This would set the low byte of D0 to hex FF if the Z flag was set.
  1823. There are two special forms:  SF  will always clear the byte, and ST will always set the byte.
  1824.  
  1825.  
  1826. SUB    Subtract.  Subtracts the first operand from the second - result in the second operand.
  1827.  
  1828.     X    Set on borrow, cleared otherwise.
  1829.     N    Set if msb is one, cleared otherwise.
  1830.     Z    Set if result is zero, cleared otherwise.
  1831.     V    Set on overflow, cleared otherwise.
  1832.     C    Same as X.
  1833.  
  1834. SUBA    Subtract Address.  Same as SUB, but used for address registers.  No flags are affected.
  1835.  
  1836. SUBI    Subtract Immediate.  Same as SUB, but used when the first operand is a numeric constant. 
  1837. Same flags set as SUB.
  1838.  
  1839. SUBQ    Subtract Quick.  Same as SUBI except that the constant is limited to 3 bits.  Same flags as
  1840. SUB.
  1841.  
  1842. SUBX    Subtract Extended.  Subtract for multi-precision numbers.  Same flags set as SUB, except that
  1843. Z will only be cleared by a non-zero result - it will not be set by zero.
  1844.  
  1845. SWAP    Swap.  Swaps the words in a single operand.  That is, bits 0-15 are swapped with bits 16-31.
  1846.  
  1847.     N    Set if bit 31 of result is set, cleared otherwise.
  1848.     Z    Set if entire result is zero, cleared otherwise.
  1849.     V    Always cleared.
  1850.     C    Always cleared.
  1851.  
  1852. TAS    Test and Set.  Tests a byte specified by the operand and sets the high order bit of that byte to
  1853. 1.  Apparently this is used to prevent two processors from grabbing the same resource - but I have
  1854. not seen it.
  1855.  
  1856.     N    Set according to the high order bit of the specified byte before the TAS command is executed.
  1857.     Z    Set if the byte is zero before the TAS is executed.
  1858.     V    Always cleared.
  1859.     C    Always cleared.
  1860.  
  1861.  
  1862. TRAP    Trap.  All traps will be presented in their Inside Macintosh equivalent so you should never
  1863. see this command.
  1864.  
  1865. TRAPV    Trap on Overflow.  If V is clear, do nothing.  If V is set, then the flags and the program
  1866. counter are pushed on the stack, and the a new program counter is loaded from absolute location 1C
  1867. hex.  I have seen this instruction, but have ignored.  Apparently some high-level languages use this
  1868. to process overflow errors.
  1869.  
  1870. TST    Test.  Tests an operand for negative or zero values.
  1871.  
  1872.     N    Set if the msb is set, cleared otherwise.
  1873.     Z    Set if zero, cleared otherwise.
  1874.     V    Always cleared.
  1875.     C    Always cleared.
  1876.  
  1877. UNLK    Unlink.  Undoes a LINK command.  The specified addres register is placed in the stack pointer
  1878. (restoring it) and a long word is popped off the stack and placed in the address register (restoring
  1879. it).  No flags are affected.
  1880.  
  1881. Using MacNosy
  1882. Before looking at an actual assembly program listing, we need to look at MacNosy.  The version I am
  1883. using is 2.95 so if you have an older version, bear with me.
  1884. What the Hell is it??
  1885. MacNosy is an incredible dissassembler.  Instead of simply converting all the hex information in a
  1886. program straight into assembler syntax, Nosy analyzes the program recursively, attempting to
  1887. determine exactly where data is located, what types of information is being used and passed to and
  1888. from procedures, etc.  Once Nosy has attacked a program, it expects you to give it some hints about
  1889. what you think is going on, then Nosy examines it again and so on until you like what you see.  The
  1890. two main types of information Nosy deals with are Code Blocks, and Data Blocks.  Code blocks are what
  1891. Nosy thinks can actually be executed while data is simply referred to by the code - but never
  1892. actually executed.  Often Nosy will be tricked into thinking that a code block is a data block.  You
  1893. will find out later how to show Nosy what is really going on.
  1894. Starting Out.
  1895. The first thing Nosy presents you with is an open dialog requesting the program to disassemble.  All
  1896. resource files will be available, but only something with executable code would make sense to
  1897. decompile - such as applications, DAs, Inits, Cdevs, etc.  Once the file to decompile has been
  1898. selected, Nosy asks if you want to view the resources.  Pressing y <Return>  will list all resources
  1899. and information pertaining to each.  Pressing n <Return> or just <Return> will skip to the next
  1900. question.  Next Nosy wants to know what type of resource to decompile.  Press return to decompile
  1901. CODE resources (for applications, and any inits, cdevs, or DAs that use CODE resources).  If CODE is
  1902. not what you want, type in the resource type - INIT for inits, DRVR for DAs, and >cdev for Cdevs (the
  1903. > is necessary).  Finally, a dialog will come up asking how you want to decompile.  Just leave all
  1904. options as is, and hit return. Nosy will go through what it terms a TreeWalk which means that it will
  1905. recursively analyze the program and generate it's decompiled code.
  1906. Working with Nosy.
  1907. Since I don't want to re-type the entire Nosy manual, I am going to list just the basics.  There are
  1908. some great features that I never use and don't even know how to initiate without referring to the
  1909. manual and these will be omitted.  Everything I use to crack software will be covered in detail.
  1910. At this point, Nosy will present you with several windows: a Code Blks window, listing all procedures
  1911. in the decompiled file; a Notes window which Nosy will use to display information; and a Mystery
  1912. window, listing things that Nosy had trouble with during decompilation.  Nosy can also display a list
  1913. of all Data Blocks which are chunks of code that either did not make sense as executable code, or
  1914. were referenced as data (Nosy looks for PEA and LEA to determine this and looks for JMP, JSR, and BSR
  1915. to find individual procedures).  Notes cannot be closed, so ignore it, and Mystery has things that -
  1916. to date at least - don't matter that much to the cracker.  When working with Nosy, you can at any
  1917. time select the name of a code or data block and hit CMD-d to display it in a new window.   Before
  1918. examining the menu commands, lets look at a basic Nosy listing and see what Nosy tells us.
  1919.  
  1920. This is the procedure called Eject from the file Font/DA Mover.  This is the file I will describe in
  1921. detail later.
  1922.  
  1923.    BD4:                                 QUAL    Eject ; b# =79  s#1  =proc47
  1924.  
  1925.                                vbt_1     VEQU  -64
  1926.                                param2    VEQU  8
  1927.                                param1    VEQU  10
  1928.                                funRslt   VEQU  14
  1929.    BD4:                                 VEND    
  1930.  
  1931.                                ;-refs -  2/CLOSEMYF  
  1932.  
  1933.    BD4: 4E56 FFC0      'NV..'  Eject    LINK    A6,#-$40
  1934.    BD8: 41EE FFC0      200FFC0          LEA     vbt_1(A6),A0
  1935.    BDC: 316E 0008 0016 2000008          MOVE    param2(A6),ioVRefNum(A0)
  1936.    BE2: 216E 000A 0012 200000A          MOVE.L  param1(A6),ioNamePtr(A0)
  1937.    BE8: A017           '..'             _Eject  ; (A0|IOPB:ParamBlockRec):D0\OSErr 
  1938.    BEA: 3D40 000E      200000E          MOVE    D0,funRslt(A6)
  1939.    BEE: 4E5E           'N^'             UNLK    A6
  1940.    BF0: 225F           '"_'             POP.L   A1
  1941.    BF2: 5C8F           '\.'             ADDQ.L  #6,A7
  1942.    BF4: 4ED1           'N.'             JMP     (A1)
  1943.  
  1944. OK, The first column contains the code resource-relative address of the instructions.  To the right
  1945. of this is the hex listing of the instruction, followed by an ascii display, followed by the actual
  1946. assembly instruction.
  1947. The first line tells you the following:  The name of the procedure (either a meaningful name Nosy
  1948. found somewhere, or a generic procN where N tells where the procedure falls sequentially in the
  1949. file), the block number (similar to proc number except this takes into account data blocks as well as
  1950. procedure blocks), the segment or CODE resource ID #, and the actual procedure number.  So in the
  1951. above example, we are looking at Eject, it is the 79th block in the file (counting data blocks), it
  1952. is in code resource ID 01, and it is the 47th procedure block in the file.  So we could open CODE 01
  1953. in Resedit, skip down to BD8 and see the hex codes that Nosy lists.  Whe BD8 and not BD4 like it says
  1954. above?  Well, on disk, a CODE resource has 4 header bytes (whose meaning escapes me at the moment) so
  1955. we have to add 4 to the Nosy address to find the correct Resedit address.
  1956. Below this information will be listed any local variables used (they will always contain an
  1957. underscore) along with their relative offsets from the procedure, then any parameters passed along
  1958. with their offsets.  If there is a result that will be passed back to the calling procedure, it will
  1959. be listed as funRslt (as it is here).  Don't worry about all the offset information as Nosy will
  1960. refer to parms and local variables by their symbolic names.  VEND denotes the end of the variable
  1961. list.  Next comes any references to this procedure - any procedures that call this procedure. 
  1962. Finally comes the actual listing.  Occasionally, Nosy will stick more than one procedure in a window. 
  1963. If this happens, each procedure will have the above header.  Nosy also might include data blocks in a
  1964. procedure's window and it will have the word dataXX to the left of it.
  1965.  
  1966.  
  1967. Menu Commands
  1968.  
  1969. 
  1970.  
  1971. This is pretty straight forward and should require no explanation.  Save As... will allow you to save
  1972. as text a procedure or data window.  This way you can type in your own comments and save them.  I
  1973. never use this feature, however.  TTY mode allows some of Nosy's extra features.  In previous
  1974. version, TTY was the only mode and I imagine was hell to use.  With the newer version, 2.0 or higher
  1975. I believe, you can stay in the window mode that you are currently in and never use TTY mode.
  1976.  
  1977. 
  1978.  
  1979. OK, the first two sections are standard.  Find will find the next occurence of whatever you have
  1980. selected.  For example, you can select a local variable name and hit cmd-f to find the next time it
  1981. occurs in the current window.  If nothing is selected, Nosy presents a dialog allowing you to enter a
  1982. search string.
  1983. Change    brings up a standard search/replace dialog - similar to Word.
  1984. Goto Line    allows the user to goto a specified line number in the front window.
  1985. Grab Clip & Find    operates like Find except that the clipboard is used as the search string.
  1986. Show Insert pt    scrolls the window to display the cursor (if you had scrolled the cursor off the
  1987. screen).
  1988. insert pt to Top    places the cursor at the top of the screen (line 1).
  1989. sel to Notes    copies the current selection into the Notes window.
  1990.  
  1991. 
  1992.  
  1993. Code|Data blk    displays the currently selected code or data block in a new window.  For example if
  1994. you select a procedure from the code blocks window and hit cmd-d, the procedure will be displayed in
  1995. a new window.  If there is no current selection then Nosy will request a proc name via a dialog.
  1996. Refs to    Active only if a procedure name is selected.  Displays all procedures that call the selected
  1997. procedure.  Using this, you can see any part of the program that is calling a particular procedure.
  1998. Call chain    Similar to Refs to.  Any procedure that calls the selected procedure is also treated with
  1999. Refs to.  For example, you select a procedure called proc5.  Doing a Refs to shows all procs that
  2000. call proc5 - let us say for example, pro10 and proc 15.  If you had selected proc5 and done a Call
  2001. chain instead of Refs to, then first proc10 would be displayed along with any proc that called and so
  2002. on backwards until the chain ends.  Then proc15 would be listed along with any procs that call it,
  2003. and so on until the chain ends.  This is an excellent way of tracing a procedure that draws an error
  2004. dialog back to the procedure that actually generated the error.
  2005. Sys syms map    Displays all system global variables along with any procedures that reference them. 
  2006. An example might be the system global MemErr which contains any OS errors.  Nosy would display any
  2007. procedures that reference MemErr - note that this command displays ALL system globals and their
  2008. referencing procedures.
  2009. Trap refs map    This is a beauty.  This will list all traps called by the program and the procedures
  2010. that call them.  If a program is asking for a key disk, use this command to search for procedures
  2011. that call either ModalDialog or one of the Alert traps.
  2012. Globals map    Displays all program global variables and the procedures that use them.
  2013. Rsrc map    Lists all program resources, their lengths, and names if any.
  2014. Strings    Lists all strings and the procedures that reference them.  I am not sure what Nosy defines as
  2015. a string, but try it on Font/DA Mover to see.
  2016. Data Blks    Displays a window listing all data blocks.
  2017. Case jumps    Displays any procs containing a structure that resembles a case statement.
  2018. Mystery procs    Opens the Mystery Procs window showing any procedures that Nosy was unsure how to
  2019. handle.
  2020. ROM Patch Info    Unknown.  My outdated docs don't even mention this command.
  2021. Bad Blks    Displays information about any blocks that Nosy thought were code but contained illegal
  2022. instructions so Nosy converted them to data blocks.  Encrypted code would fit into this category.
  2023. Blk tbl    Displays the following for all blocks: name, segment number (resource ID #), start address,
  2024. and length.
  2025. Code Blks    Displays the Code Blks window listing all code blocks.
  2026.  
  2027. 
  2028.  
  2029. Review...    Lets you review data blocks, optionally converting them to code blocks.  More on this
  2030. later.
  2031. Link Jmp to Tbl    Defines the link between a mystery jump and and a data block.  To use it, select the
  2032. address of a mystery JMP and choose the command.  More on Jump Tables later.
  2033. Code to Data    Converts a selected code block to a data block.  The blocks name won't change until
  2034. the next Explore (see below).
  2035. Is Proc    Converts a selected data block to a code block.  The block's name won't change until the next
  2036. Explore.
  2037. JSR is JMP    Tells Nosy that a JSR is really a JMP.  Sometimes a JSR is followed by data - which will
  2038. look like jiberish code.  The called procedure then pops the return address off the stack and uses
  2039. that address as a pointer to a data block with no intention of returning to the calling procedure. 
  2040. To use this command, select the destination of the JSR (e.g. for JSR  proc100, select proc100) and
  2041. choose this command.
  2042. Explore    Initiates a TreeWalk.  This allows Nosy to re-examine the program using any changes you might
  2043. have made (i.e. converting data blocks to code blocks, etc).
  2044.  
  2045. 
  2046.  
  2047. Extract Comments    Extracts comments from the selection (usually an entire procedure window) into a
  2048. window entitled Comments.  See section on commenting below.
  2049. Append to .aci    Appends selected comments (created using the above) to an aci (additional comment
  2050. information) file.  Later, this file can be re-merged into the dissassembly.
  2051. name cHange    Changes the selected name to whatever you type in.  Use this to rename procedures from
  2052. the generic procN to a name that tells you what the procedure basically does.  The change will be
  2053. immediate and global.
  2054. Addr to File pos    Converts a selected address (the leftmost information for a procedure display)
  2055. into file-relative information, displaying a file-relative offset (in hex), block or sector number,
  2056. and the block offset to the start of the address.  This might be handy if you were using a file
  2057. editor (instead of Resedit which allows you to simply open the proper code resource) to edit the
  2058. file.
  2059. Convert to .asm fmt    Converts the current procedure window to asm format by removing the addresses and
  2060. hex and ascii data.  Cannot be undone - you must close the window, not save changes, and re-open it.
  2061. save .snt, reRead .aci    Saves a .snt file for the dissassembled program and re-reads the comment file
  2062. if it exists.  .snt files (saved Nosy tables) are a means of saving your dissassembly mid-session. 
  2063. All changes are remembered so when you re-open the file later, you begin right where you left off
  2064. instead of doing a TreeWalk all over again, etc.
  2065. Journal commands    A checkmark next to this indicates that all your commands are being saved to a
  2066. text file.  The file will not actually be saved unless you specify so when you Quit - see quitting
  2067. later.
  2068. Proc rel addresses    When checked displays the address of each instruction as procedure relative
  2069. (starting at zero for each procedure instead of starting at zero for each code resource).
  2070. format Maps by Addr    When checked, Nosy will change the way it displays its various maps, i.e. Sys
  2071. syms, Trap refs, etc. under the Display menu.  Instead of proc names, Nosy will display the segment
  2072. number, and the segment offset.  But - if Proc rel addresses is also checked, then Nosy will replace
  2073. the proc names with a proc name followed by a + followed by the procedure relative offset.  Try it
  2074. out if this doesn't make sense.
  2075. cmds to Notes Wind    Not yet implementated - like a lot of great features (see below).
  2076. Set Source Path    Not in my manual - you're on your own.
  2077. Extract Map Names    Not in my manual - on you're own again.  This doesn't seem to do anything,
  2078. though, when I try it.
  2079.  
  2080. Unfortunately, the Search_Rsrc menu is totally disabled.  Maybe the next version...
  2081.  
  2082. 
  2083.  
  2084. Record/ALL names    Lists all Macintosh data structures that Nosy currently knows.
  2085. Fields of    Depends on the selection:  1) a datatype (e.g. Dialog Record - or anything listed by the
  2086. previous command) - describes all fields for the datatype.  2) datatype@address - displays the
  2087. current values for the datatype if one exists at the specified address.  3) @address - displays
  2088. hex/ascii dump at specified address.
  2089. OS Traps    Lists all known Operating System Traps and their parameters.
  2090. TB Traps    Lists all known ToolBox traps and their parameters.
  2091. Sys Syms    Lists all known System Symbols.
  2092. Sys Errs    Lists all known System Errors and their codes.
  2093. Constants    Lists all known Macintosh Constants.  Note that my copy of Nosy contains an error in this
  2094. window - it specifies that constants in brackets can be selected and viewed by pressing cmd-?.  Use
  2095. cmd-<space> (or select Fields of from the Tables menu).
  2096. Ascii    Decimal/Hex/Ascii lookup table.
  2097. Calculate    Evaluates selected expressions which can contain mathematical operators, system globals,
  2098. program globals, IM datatypes,  registers etc.  Use # to force decimal (#10) and $ for hex ($10).
  2099. Convert Hex to Dec    Converts a selected number to decimal, ascii, and system symbol equivalent if
  2100. there is one.
  2101. add/ZAP Type /Defs    No idea.
  2102.  
  2103. Note on commands requiring a selection (Calculate, etc.)  You may have noticed that often there is no
  2104. place to enter the text you want to select.  In cases like these, type your text into the Notes
  2105. window, select it, and choose the command you wish.
  2106.  
  2107.  
  2108. Reviewing Data Blocks
  2109. This is the process by which you tell Nosy that it has mistakenly made a piece of code a data block. 
  2110. Once you initiate the Review... command, Nosy will show you each data block in sequence and give you
  2111. a chance to work on it.  Note that you may never need to do this to crack a program - god knows I
  2112. never use it unless I am really having problems.  This section is to provide you with some idea of
  2113. what Nosy can do.
  2114. Here is a typical display after selecting Review... from the Reformat menu.  The Data Blk window
  2115. displays the data block, the window directly underneath this will display the section of code that
  2116. references that data block (if their is one) and the Cmd window awaits your input.  There are about a
  2117. zillion things you can do, but the most important one is the c command.
  2118. 
  2119.  
  2120. If your press c and return, Nosy shows you what the data block looks like in assembly:
  2121. 
  2122. Notice that this looks like pretty good code!  Also note that Nosy has placed i in the Cmd window
  2123. anticipating that you will want to change this to code.  Here are all the commands available:
  2124.  
  2125. H    takes 2 parameters: 1) either L,W, or B for Longword, Word, or Byte and 2) the number of entries
  2126. per line.  Formats the block as Hex bytes.  Example: HL2 would format the block as hex longwords, 2
  2127. per line.
  2128. D    same as H (above) but formats block as decimal entries.
  2129. A    same as H (above) but formats the block as ascii entries.
  2130. Z    same as H (above) but formats the block as zero entries.
  2131. W    Formats the block as a word-aligned Pascal string.
  2132. S    Formats the block as a Pascal string.
  2133. WZSTR    Formats the block as a word-aligned zero-terminated string.
  2134. Z    Formats the block as a zero-terminated string.
  2135. J    Formats the block as a set of Jump Table entries - each word is taken as an offset from the
  2136. beginning of the data block to a common procedure and these jumped to spots are marked as common
  2137. blocks (a common block - denoted com_nn - is any procedure executed via JMP instead of JSR or BSR). 
  2138. If you do this, you need to use the Link Jmp to Tbl command to link the jump table to its jump
  2139. command.  See Jump Tables below.
  2140. JUMPP    Same as J except that the entry points are marked as procedures instead of common blocks.
  2141. BRAL    Formats the block as code.  Any instructions that are BRAnched to are marked with local
  2142. markers (as in a standard Nosy listing).
  2143. BRAC    Same as above except that instructions reached via BRA are marked as common blocks.
  2144. U    Undoes any formatting changes.
  2145. C    Changes the block to a code listing and brings up the code menu - discussed below.
  2146. Q    Exits Review mode.
  2147. N    takes an integer parameter X.  Splits the block into two blocks, the first block getting X words
  2148. (remember a word is two bytes).
  2149. NB    same as above except the parameter specifies bytes instead of words.
  2150. NL    same as above except the parameter is a segment-relative address specifying the end of the the
  2151. first block.
  2152. NU    takes an optional search string as parameter.  Splits the block with the first block ending upon
  2153. finding the search string.  If no string is supplied, Nosy searches for a logical procedure end (RTS,
  2154. JMP(AX) ).  The block is formatted as code and the code menu is displayed.
  2155. NW    Splits the block in two, the first block being made a word-aligned Pascal string.
  2156. N*    Splits the block in two.  Uses the first longword to determine the length of the first block.
  2157. O    If the previous block is a data block, then combine it with the current one.
  2158. ADDR    Formats the block as a list of word-length procedure block addresses.
  2159. LADRC    Formats the block as a list of longword-length common block addresses.
  2160. LADRP    Formats the block as a list of longword-length procedure block addresses.
  2161. <Return>    Saves changes, and takes you to the next block.
  2162.  
  2163. The Code Menu Commands:  these come up if you use c or nu to change the block to a code listing.
  2164.  
  2165. U    Undo any changes to size or format and takes you back to the Review menu.
  2166. I    Tells Nosy to keep the block as code and return to the Review menu.
  2167. Q    Exits Review mode.
  2168. R    Changes block back to data, but retains any size changes you may have made.
  2169. N    Same as the N commands above.
  2170. <Return>    Same as above - returns to the Review menu.
  2171.  
  2172. Once you have finished Reviewing data blocks, you must select Explore from the Reformat menu to have
  2173. Nosy incorporate any changes into its lists.
  2174.  
  2175.  
  2176. Working with Jump Tables
  2177.  
  2178. A jump table is a means of efficiently transferring control to a procedure.  An example of a jump
  2179. table would be a program that receives an event (as most mac programs do) and then has to execute a
  2180. procedure depending on what the event was.  Font/DA Mover has an extermely simple jump table -
  2181. actually it is not a true jump table - in which the button the user clicks is returned to its main
  2182. event loop as an integer.  The program then repeatedly subtracts one from the integer and branches to
  2183. an appropriate procedure when the integer has been reduced to zero.  A more common (and true) jump
  2184. table consists of a list of offsets.  The program then takes an integer which tells it which entry in
  2185. the table to use, multiplies it by 2 (assuming each entry is two bytes in length) and then indirectly
  2186. jumps to the correct procedure.  Here is an example taken from the Nosy manual (this is from the
  2187. System File's .MPP driver):
  2188.  
  2189. LEA    data4,A3
  2190. ADDA    D3,A3
  2191. ADDA    D3,A3
  2192. MOVEA    (A3),A3
  2193. PEA    .MPP
  2194. ADDA.L    (A7)+,A3
  2195. JMP    (A3)
  2196.  
  2197. data4    DC.W    $82,$280,$26C,$3C, etc
  2198.  
  2199. As gross as this looks, lets see what it is doing.  At the start, D3 contains the selector that
  2200. determines which entry in the table to use.  A3 is loaded with the address of the jump table.  D3 is
  2201. added to it twice (we could have doubled D3, then added it) so that now A3 contains the address of
  2202. the proper jump table entry.  The instruction MOVEA   (A3),A3 grabs the jump table entry (which is
  2203. simply an offset from the start of the program to the correct procedure) and puts that entry back
  2204. into A3.  Next the address of the program start (.MPP) is pushed on the stack, and this value is
  2205. added to A3 to produce the actual address of the procedure (the address is the start of the program
  2206. plus the offset).  Now A3 is setup, so the program Jumps to the address in A3.  If you don't mind
  2207. looking at this type of listing (and I don't since it probably is not the copy protection - although
  2208. it might be jumping to the copy protection) then you need go no farther.  But Nosy can set this up to
  2209. look much nicer.
  2210. To fix this up, select the address (the far left column) of the Jump instruction - in this case, the
  2211. JMP (A3).  Now choose Link Jmp to Tbl from the Reformat menu and a dialog box appears requesting the
  2212. name of the jump table's block - in our case that would be data4.  Click continue and a new dialog
  2213. appears.  The first thing we need is the table format.  There are three choices: JUMPP - tells nosy
  2214. to label the jumped to procedures as procedure blocks; JUMPC - tells Nosy to label the jumped to
  2215. procedures as common blocs; JUMPL - tells Nosy to label the jumped to procedures with local labels in
  2216. the same block as the jump table.  To figure out which one to use (and it is really a matter of
  2217. preference), decide if you want to break the whole thing up into many procedures, or keep it as one
  2218. large procedure with tons of local labels.  If the procedure is a massive one, you may want to break
  2219. it up (and I would recommend JUMPP - but then, I like proc labels better than com labels), otherwise,
  2220. use JUMPL.
  2221. Next we need the number of jumps.  Just count the number of entries - but be careful: you need to
  2222. decide the size of each entry in the table.  Note the DC.W  next to data4.  This means that Nosy is
  2223. showing you individual words so you can just count the number of entries.  But if Nosy is using DC.B,
  2224. then it is showing you bytes, so you would have half as many word length entries.
  2225. Finally, we need the Table Bias.  Bias is a parameter that Nosy uses to determine the actual
  2226. procedure address of a non-standard jump table.  To calculate this, use this formula:  Bias = Address
  2227. of JumpTable + Offset - TargetAddress.  The tricky thing is to deterine the TargetAddress.  In the
  2228. above example, it is easy, since the code clearly refers to the start of itself (it refers to the
  2229. address of .MPP).  JumpTable is the address (leftmost column in the listing) of the start of the jump
  2230. table, and Offset is the first word-length offset in the table.  Note that your calculations will
  2231. result in a hex bias - Nosy needs you to change it to decimal.
  2232.  
  2233. Click Accept, do another Explore, and that is it!  Now the listing looks like:
  2234.  
  2235.     JMP    (A3)
  2236.  
  2237.     JBIAS    92
  2238. data4    JUMP    procA
  2239.     JUMP    procB
  2240.     JUMP    procC
  2241.     etc.
  2242. Notice that Nosy uses JUMP to distinguish it from the instruction JMP.  Once this is set up, it is a
  2243. cinch to see where the jump table is jumping - provided you can deduce the selector.  Most of the
  2244. time Nosy works wonders with jump tables, and the few times it has problems (it will list these
  2245. problems in the Mystery window) I have found it not worth the work to convert them to the above
  2246. format.
  2247. Commenting Your Listings
  2248.  
  2249. There are a couple of cool features that I am not going to explain regarding commenting simply
  2250. because I have never used them and the manual I have isn't the most verbose.  Basically, you can put
  2251. comments on any line that Nosy hasn't already commented.  All comments must start with a semi-colon. 
  2252. Once you have all the comments you want, do a cmd-a to select all, and choose Extract Comments from
  2253. the Misc menu.  Nosy will extract all your comments into a comments window.  Now hit cmd-a again, and
  2254. choose Append to .aci from the Misc menu.  This will save your comments.  Now close the procedure
  2255. window and don't save changes.  Select Save .snt, reRead .aci from the Misc menu.  Nosy may ask you
  2256. if you want to delete something or other which it claims saves space in the Debugger.  Since we are
  2257. not using the Debugger, choose No.  Now when you open the procedure again, you comments appear.
  2258. There is one feature I will attempt to explain, because it could be a serious boon.  There a several
  2259. slash (/) commands Nosy understands.  One in particular, /w, works like this:  Anytime a register is
  2260. setup to contain a pointer to a Mac structure, you can have Nosy automatically show the structure
  2261. whenever the register is referenced.  Here is an example:
  2262.  
  2263.         PEA    data24        ; len = 206
  2264.         _OpenPort  ;  (port:GrafPtr)
  2265.         LEA    data24,A2    ; len = 206
  2266.         MOVE    #4,68(A2)
  2267.         MOVE    #9,74(A2)
  2268.  
  2269. Note in the 3rd line that A2 is given the GrafPtr.  Since GrafPtr is a pointer to a valid Mac
  2270. structure (GrafPort), we could use the /w command as follows:  click at the end of the 3rd line and
  2271. hit return (so we are not commenting on a line that Nosy has already commented).  Enter
  2272. /w<space>GrafPort.  Now save the comments as illustrated above.  When the proc is re-opened it shows
  2273. the following:
  2274.  
  2275.         PEA    data24        ; len = 206
  2276.         _OpenPort  ;  (port:GrafPtr)
  2277.         LEA    data24,A2
  2278.         /w GrafPort
  2279.         MOVE    #4,txFont(A2)
  2280.         MOVE    #9,txSize(A2)
  2281.  
  2282. Using this technique, Nosy will use the fields of the structure instead of the actual offsets from
  2283. the register.  This will work for any valid Mac structure.  I haven't used this feature (I just
  2284. noticed it when compiling this manual) so that is all I will say - feel free to experiment.
  2285. Well, I guess the next thing to do is start looking at some serius code listings pulled directly from
  2286. Nosy (and not stuff I made up on the fly).  Nosy has shorthand notations for certain operations, most
  2287. commonly for stack operations.  The two to watch out for are PUSH and POP (btw, TMON does not use
  2288. this notation, but rather uses the standard notation found in any assembly book).  PUSH is the
  2289. equivalent of putting the operand onto the stack using auto pre-decrement.  POP is the same as
  2290. grabbing the operand off the stack using auto post-increment.
  2291. Let's take a look at some code listings from Font/DA Mover 3.8.  I selected this program so that you
  2292. can pull up the same listings that I will refer to in Nosy.  First take a look at the initial
  2293. procedure:  DA Mover.  There will always be a procedure whose name is the same as the program you are
  2294. de-compiling.  This procedure (DA Mover in this case) is the first procedure the program executes
  2295. when launched.
  2296.  
  2297.    430:                                 QUAL    DA Mover ; b# =12  s#1  =proc4
  2298.  
  2299. OK, I will stick my notes right in the listing (below or to the right of what I am refering to), so
  2300. bear with me.  Note the first line (above).  We are looking at block 12, segment (or CODE resource #)
  2301. 1, and it is the 4th procedure in the program.
  2302. The first few lines will do some startup stuff that I do not fully understand and so I will skip it.
  2303.    430: 4EBA 0C48      100107A DA Mover JSR     proc70    Proc 70 is just an RTS
  2304.    434: 4E56 0000      'NV..'           LINK    A6,#0
  2305.    438: 2C5F           ',_'             POP.L   A6
  2306.    43A: 4EBA 0C40      100107C          JSR     proc71    Proc 71 calls _RTINIT which seems to be a
  2307. common step for MPW compiled programs.  It then initializes some global variables.  Let's skip all
  2308. this.
  2309.    43E: 486D 024A      3000000          PEA     proc232(A5)
  2310.    442: A9F1           '..'             _UnLoadSeg ; (Proc:ProcPtr)  Here we are dumping an un-needed
  2311. procedure.
  2312. Now, looking at the listing from here, notice the procedures that get called - two without labels,
  2313. then SetUp, MakeAWin and FinderSE and finally MainEven which sounds suspicially like an event loop. 
  2314. Let's check out these procedures.
  2315.    444: 4EBA 05E2      1000A28          JSR     proc28    If you look at this procedure, you see
  2316. several references to memory stuff like ApplHeap, ApplZone, Rom85, etc.  Looks like this is checking
  2317. for enough memory or something.  Not too interesting.
  2318.    448: 4EBA 021E      1000668          JSR     proc10    This proc looks to be changing a few traps. 
  2319. Note that it allocates a new pointer (NewPtr trap) and then calls GetTrapAddress, and then
  2320. SetTrapAddress.
  2321.    44C: 4EAD 01F2      2005092          JSR     SETUP(A5)    Take a look at this listing below the
  2322. current one:
  2323.    450: 4EAD 01FA      2005852          JSR     MAKEAWIN(A5)    Draw the main dialog.
  2324.    454: 4EBA FCC2      1000118          JSR     FINDERSE    Checks if user launched a suitcase and if
  2325. so, opens it.
  2326.    458: 4AAD F4F0        -$B10          TST.L   glob26(A5)    Verify the main memory handle.
  2327.    45C: 6706           1000464          BEQ.S   lae_1    Branch if it is empty.
  2328.    45E: 4EBA FBA0      1000000          JSR     MAINEVEN    Do the actual program until user Quits.
  2329.    462: 6008           100046C          BRA.S   lae_2    Exit without error.
  2330.    464: 3F3C 0031      '?<.1'  lae_1    PUSH    #49    Out of Memory Error.
  2331.    468: 4EAD 01CA      200023C          JSR     DOALERT(A5)    Do an Out of Memory alert
  2332.    46C: 4EBA FF86      10003F4 lae_2    JSR     DOCLEANU    From here, the program exits.
  2333.    470: 4EAD 01D2      20002B2          JSR     MYEXITTO(A5)
  2334.    474: 4EBA 0C2A      10010A0          JSR     %INITHEA
  2335.    478: 4EBA 0C2C      10010A6          JSR     proc73
  2336.    47C: 4E75           'Nu'             RTS     
  2337.  
  2338.    47E: 4E5E 4E75 C64F 4E54    data9    DNAME   FONT_DA_,4
  2339.  
  2340.    48A: '..'                   data10   DC.W    0
  2341. Here is the SetUp Procedure:
  2342.  
  2343.   5092:                                 QUAL    SETUP ; b# =467  s#2  =proc199
  2344.  
  2345.                                vho_1     VEQU  -12    Only one local variable, no parameters.
  2346.   5092:                                 VEND    
  2347.  
  2348.                                ;-refs -  1/DA Mover      Only called via DA Mover.
  2349.  
  2350.   5092: 4E56 FEE6      'NV..'  SETUP    LINK    A6,#-$11A    Setup a Stack frame for local variables
  2351.   5096: 48E7 0118      'H...'           MOVEM.L D7/A3-A4,-(A7)    Save D7,A3 and A4 on stack
  2352.   509A: 7E01           '~.'             MOVEQ   #1,D7    Loop coming up, this inits the loop counter.
  2353.   509C: 6006           20050A4          BRA.S   lho_2    And branch into the loop.
  2354.  
  2355.   509E: 4EAD 00D2      1000AB0 lho_1    JSR     MoreMasters(A5)
  2356.   50A2: 5247           'RG'             ADDQ    #1,D7    Increment loop counter.
  2357.   50A4: 700F           'p.'    lho_2    MOVEQ   #15,D0
  2358.   50A6: B047           '.G'             CMP.W   D7,D0    Test if loop done...
  2359.   50A8: 6CF4           200509E          BGE     lho_1    If not, branch back.
  2360. OK, take a look at the above code.  First, D7 is initialized to 1 and then the program branches down
  2361. to lho_2.  The loop test is setup here (15 is the end of the loop).  At the compare, ask yourself, is
  2362. D0 greater than or equal to D7?  Well, the first time, D0 is 15 and D7 is 1 so the loop branch will
  2363. execute.  So, MoreMasters is called, 1 is added to the loop counter, and then the loop is checked
  2364. again.  This will loop 15 times (until D7 has 16 in it).  MoreMasters is a trap (in this case, the
  2365. procedure called MoreMasters will execute the trap) that causes a block of master pointers to be
  2366. allocated in the current heap zone.  See Inside Mac's (here on referred to as IM) Memory Manager
  2367. section for a better description.
  2368.   50AA: 486D F420        -$BE0          PEA     glob3(A5)    Push the address of glob3 on the stack.
  2369.   50AE: A86E           '.n'             _InitGraf ; (globalPtr:Ptr) InitGraf, we see in IM, that
  2370. InitGraf must be called once near the start of a program.  It requires one parameter, a pointer to
  2371. the first QD global variable. This parameter is first pushed on the stack in the previous
  2372. instruction.
  2373.   50B0: A8FE           '..'             _InitFonts      These traps can all be found in IM.
  2374.   50B2: A912           '..'             _InitWindows  
  2375.   50B4: 2F3C 0000 FFFF '/<....'         PUSH.L  #$FFFF
  2376.   50BA: 201F           ' .'             POP.L   D0
  2377.   50BC: A032           '.2'             _FlushEvents ; (whichMask,stopMask:EventMask) 
  2378.   50BE: A9CC           '..'             _TeInit  
  2379.   50C0: 42A7           'B.'             CLR.L   -(A7)    Note that InitDialogs needs a ProcPtr (a long
  2380. word).  The clr command here uses auto pre-decrement to push a NIL pointer onto the stack.
  2381.   50C2: A97B           '.{'             _InitDialogs ; (resumeProc:ProcPtr) 
  2382.   50C4: A930           '.0'             _InitMenus  
  2383.   50C6: 486E FFF4      200FFF4          PEA     vho_1(A6)    OK, notice the VAR in the trap below. 
  2384. This means that info will be returned via the parameter we push on the stack.  So, after the trap,
  2385. vho_1 will be a GrafPtr (whereas before the trap, god knows what is in it).
  2386.   50CA: A910           '..'             _GetWMgrPort ; (VAR wPort:GrafPtr) 
  2387.   50CC: 2F2E FFF4      200FFF4          PUSH.L  vho_1(A6)    Now, our GrafPtr is used to set the
  2388. current Port.
  2389.   50D0: A873           '.s'             _SetPort ; (port:GrafPtr) 
  2390.   50D2: 206E FFF4      200FFF4          MOVEA.L vho_1(A6),A0    Now A0 contains our GrafPtr.
  2391.   50D6: 4868 0008      'Hh..'           PEA     8(A0)    This instruction says to add 8 to A0,and push
  2392. that address on the stack.
  2393.   50DA: A87B           '.{'             _ClipRect ; (r:Rect) 
  2394.   50DC: 2F3C 000E 000C '/<....'         PUSH.L  #$E000C    The MoveTo trap requires two integers to be
  2395. passes, but only one value is being pushed on the stack.  Since the instruction says to push long, 4
  2396. bytes are being put on the stack, and an integer is only two bytes.  Even though one instruction is
  2397. being used, there are actually two parameters being passed to the MoveTo trap.
  2398.   50E2: A893           '..'             _MoveTo ; (h,v:INTEGER) 
  2399.   50E4: 3F3C 0029      '?<.)'           PUSH    #41
  2400.   50E8: 4EBA CE84      2001F6E          JSR     DRAWRESS    It turns out that DRAWRESS will draw the
  2401. 41st string in the STR# resource.  If you look in Resedit, you will see that this is "3.8" the
  2402. version number.
  2403.   50EC: 3F3C 000C      '?<..'           PUSH    #12    Note the lack of a size specifier.  Remember that
  2404. this means use the word (two bytes) size.  Textsize needs an integer and IM tells us that an integer
  2405. is two bytes - or one word.
  2406.   50F0: A88A           '..'             _TextSize ; (size:INTEGER) This is pretty easy - sets the
  2407. fontsize to 12 point.
  2408.   50F2: 422D F4EF        -$B11          CLR.B   glob25(A5)    Here is the .B size specifier, meaning
  2409. clear only the low byte of glob25.
  2410.   50F6: 42A7           'B.'             CLR.L   -(A7)
  2411.   50F8: 3F3C 0004      '?<..'           PUSH    #4
  2412.   50FC: A9B9           '..'             _GetCursor ; (cursorID:INTEGER):CursHandle 
  2413. OK, this is a slightly different trap, since it returns something on the stack - as evidenced by the
  2414. colon and description at the end of the trap parameter list (:CursHandle).  Since this trap returns a
  2415. value on the stack (and not with a passed pointer as with the GWMgrPort above), the program will
  2416. first clear enough stack space to hold that value.  Thus the CLR.L -(A7).  The trap returns a handle
  2417. which is 32 bits or a long word.  The trap needs an integer, so the program pushes the word 4 onto
  2418. the stack.  Next, the program will pop the CursHandle returned by the trap off the stack into the
  2419. variable glob24.
  2420.   50FE: 2B5F F4EA        -$B16          POP.L   glob24(A5)    This the CursorHandle.
  2421.   5102: 1F3C 0002      '.<..'           PUSH.B  #2
  2422.   5106: 4EBA AEF8      2000000          JSR     SETTHECU    This subroutine is setting the cursor. 
  2423. If you look at it, you will see that it looks at the parameter passed (2 in this case) as well as
  2424. glob25 (0 in this case).  When called from here, it will pass down to the 2nd SetCursor and use the
  2425. CursorHandle in glob24.
  2426.   510A: 42A7           'B.'             CLR.L   -(A7)    Once again, clear space on the stack for a
  2427. returned handle.
  2428.   510C: 2F3A 0144      2005252          PUSH.L  data260     ; 'PACK'
  2429.   5110: 3F3C 0003      '?<..'           PUSH    #3    GetResource needs the resource type and the ID#
  2430. to load.
  2431.   5114: A9A0           '..'             _GetResource ; (theType:ResType; ID:INTEGER):Handle 
  2432.   5116: 285F           '(_'             POP.L   A4    Pop the handle (to the PACK resource) into A4.
  2433.   5118: 2F0C           '/.'             PUSH.L  A4    And push it back on the stack so HNoPurge can use
  2434. it.
  2435.   511A: 4EAD 00CA      1000AA6          JSR     HNoPurge(A5)    Once again we see a subroutine with
  2436. the same name as a trap.  You can bet that the trap will be called somewhere in the subroutine.
  2437.   511E: 42A7           'B.'             CLR.L   -(A7)
  2438.   5120: 2F3A 0130      2005252          PUSH.L  data260     ; 'PACK'
  2439.   5124: 3F3C 0006      '?<..'           PUSH    #6
  2440.   5128: A9A0           '..'             _GetResource ; (theType:ResType; ID:INTEGER):Handle 
  2441.   512A: 285F           '(_'             POP.L   A4
  2442.   512C: 2F0C           '/.'             PUSH.L  A4
  2443.   512E: 4EAD 00CA      1000AA6          JSR     HNoPurge(A5)
  2444. OK, the previous several lines have basically loaded two resources, PACK #3, and PACK #6.  The
  2445. handles to the two resources have been made non-purgeable meaning that the memory manager will not
  2446. remove them to create free space.
  2447.   5132: 42A7           'B.'             CLR.L   -(A7)
  2448.   5134: 3F3C 0001      '?<..'           PUSH    #1
  2449.   5138: 4EAD 0182      1000D8C          JSR     proc61(A5)    This little gem invokes Pack6.  My
  2450. understanding of the package manager is less than it should be, but it looks to me like this says do
  2451. a Pack6 with a selector of 1.  Hell, lets just look at proc 61...
  2452.  
  2453.  
  2454.    D8C: 7406           't.'    proc61   MOVEQ   #6,D2    OK, here is the selector (and not the 1
  2455. passed from the above procedure). So we are going to be calling the IUGetIntl procedure (I think)
  2456. with a parameter of 1 (passed from the calling procedure.  Look in IM for details of this trap and
  2457. its parameters.
  2458.    D8E: 205F           ' _'             POP.L   A0    This pops the parameter passed,
  2459.    D90: 3F02           '?.'             PUSH    D2    so that the selector parameter can be put ahead
  2460. of it on the stack.
  2461.    D92: 2F08           '/.'             PUSH.L  A0    Now the 2nd parm can be put back on the stack and
  2462. the trap called.
  2463.    D94: ADED           '..'             _Pack6  AutoPop; (selector:INTEGER)
  2464.  
  2465.  
  2466.  
  2467.   513C: 285F           '(_'             POP.L   A4    proc 61 is returning a handle to the intl
  2468. resource that it loaded, so save it in A4.
  2469.   513E: 2F0C           '/.'             PUSH.L  A4
  2470.   5140: 4EAD 00CA      1000AA6          JSR     HNoPurge(A5)
  2471.   5144: 42A7           'B.'             CLR.L   -(A7)
  2472.   5146: 2F3A 010A      2005252          PUSH.L  data260     ; 'PACK'
  2473.   514A: 3F3C 0007      '?<..'           PUSH    #7
  2474.   514E: A9A0           '..'             _GetResource ; (theType:ResType; ID:INTEGER):Handle 
  2475.   5150: 285F           '(_'             POP.L   A4    A4 now has a handle to Pack #7.
  2476.   5152: 2F0C           '/.'             PUSH.L  A4
  2477.   5154: 4EAD 00CA      1000AA6          JSR     HNoPurge(A5)
  2478.   5158: 4EAD 0172      1000D7C          JSR     proc59(A5)    This proc calles Pack2 with a selector of
  2479. 2.  This reads the Disk Initialization package into memory.
  2480.   515C: 42A7           'B.'             CLR.L   -(A7)    Clear space on stack for a returned handle.
  2481.   515E: 2F3A 00EE      200524E          PUSH.L  data259     ; 'ICON'
  2482.   5162: 4267           'Bg'             CLR     -(A7)    Push the integer 0.
  2483.   5164: A9A0           '..'             _GetResource ; (theType:ResType; ID:INTEGER):Handle 
  2484.   5166: 285F           '(_'             POP.L   A4    A4 has a handle to Icon resource ID 0.
  2485.   5168: 42A7           'B.'             CLR.L   -(A7)
  2486.   516A: 2F3A 00E2      200524E          PUSH.L  data259     ; 'ICON'
  2487.   516E: 3F3C 0001      '?<..'           PUSH    #1
  2488.   5172: A9A0           '..'             _GetResource ; (theType:ResType; ID:INTEGER):Handle 
  2489.   5174: 285F           '(_'             POP.L   A4    A4 has a handle to Icon resource ID 1.
  2490.   5176: 4267           'Bg'             CLR     -(A7)    Make space for the returned RefNum.
  2491.   5178: A994           '..'             _CurResFile ; :RefNum     Note - no parameters passed.
  2492.   517A: 3B5F FFE0         -$20          POP     glob58(A5)    Pop off the returned RefNum.
  2493.  
  2494.   517E: 486D FEDE        -$122          PEA     glob56(A5)
  2495.   5182: 3F3C 000D      '?<..'           PUSH    #13
  2496.   5186: 4EAD 002A      100048C          JSR     proc5(A5)    Here is proc5 again - the string getter. 
  2497. If you remember (from looking at DRAWRESS), the 1st parm is the string ptr, and the 2nd is the string
  2498. # to get.  This is returning a ptr to the string "The quick brown fox..." in glob56.
  2499.   518A: 7000           'p.'             MOVEQ   #0,D0
  2500.   518C: 2B40 FED4        -$12C          MOVE.L  D0,glob52(A5)
  2501.   5190: 7000           'p.'             MOVEQ   #0,D0
  2502.   5192: 2B40 FECC        -$134          MOVE.L  D0,glob50(A5)
  2503.   5196: 7000           'p.'             MOVEQ   #0,D0
  2504.   5198: 2B40 F61E        -$9E2          MOVE.L  D0,glob41(A5)
  2505.   519C: 3B7C FFFF F616   -$9EA          MOVE    #$FFFF,glob38(A5)
  2506.   51A2: 426D F614        -$9EC          CLR     glob37(A5)
  2507.   51A6: 7000           'p.'             MOVEQ   #0,D0
  2508.   51A8: 2B40 F610        -$9F0          MOVE.L  D0,glob36(A5)
  2509.   51AC: 7000           'p.'             MOVEQ   #0,D0
  2510.   51AE: 2B40 F61A        -$9E6          MOVE.L  D0,glob40(A5)
  2511.   51B2: 7034           'p4'             MOVEQ   #52,D0
  2512.   51B4: 2B40 F5FE        -$A02          MOVE.L  D0,glob31(A5)
  2513. The above instructions have simply initialized several global variables.  We don't care what they
  2514. mean at this point.  If you like, you can write down what has been set to what, but I would only
  2515. recommend this if later on you need to know explicitly what a global contains.
  2516.   51B8: 42A7           'B.'             CLR.L   -(A7)
  2517.   51BA: 7002           'p.'             MOVEQ   #2,D0    Note the MoveQ.  Remember, this is the same
  2518. as MOVE.L (except it executes faster).
  2519.   51BC: 2F00           '/.'             PUSH.L  D0
  2520.   51BE: 4EAD 009A      1000A5C          JSR     NewHandle(A5)    NewHandle is a trap that returns a
  2521. handle to a block of memory whose size is in D0.  It makes sense to guess that this procedure will do
  2522. essentially the same thing - and after checking, it certainly does.
  2523.   51C2: 2B5F F622        -$9DE          POP.L   glob42(A5)    So glob42 has a handle to a 2 byte chunk
  2524. of memory.
  2525.   51C6: 426D F626        -$9DA          CLR     glob43(A5)
  2526.   51CA: 70FF           'p.'             MOVEQ   #-1,D0    Here is one of those cases where the sign bit
  2527. is important.  Remember that the -1 is sign extended to 32 bits so D0 is being set to all binary ones
  2528. (-1 in binary).
  2529.   51CC: 2B40 F602        -$9FE          MOVE.L  D0,glob32(A5)
  2530.   51D0: 42A7           'B.'             CLR.L   -(A7)
  2531.   51D2: 2EB8 02F0         $2F0          MOVE.L  DoubleTime,(A7)
  2532.   51D6: 7002           'p.'             MOVEQ   #2,D0
  2533.   51D8: 2F00           '/.'             PUSH.L  D0
  2534.   51DA: 4EAD 01A2      1001120          JSR     proc76(A5)    This is a gross looking (i.e. no Traps
  2535. anywhere) procedure so I am not going to attempt to figure it out.  You will want to use the
  2536. technique a lot (the "Too Gross" technique) to determine which procedures to spend time with.
  2537.   51DE: 2B5F F5F6        -$A0A          POP.L   glob29(A5)
  2538.  
  2539.   51E2: 207C 0000 0AD8    $AD8          MOVEA.L #SysResName,A0    Put a pointer to the System File's
  2540. name in A0.
  2541.   51E8: 43ED F4F6        -$B0A          LEA     glob28(A5),A1    Put the address of glob28 in A1.
  2542.   51EC: 703F           'p?'             MOVEQ   #63,D0    Set up D0 as a loop counter.
  2543.   51EE: 22D8           '".'    lho_3    MOVE.L  (A0)+,(A1)+    This moves 4 bytes from A0 to A1.  Note
  2544. the use of auto post increment to automatically move the pointers to the next available data each
  2545. time.  This moves 4 bytes of the System name into glob28.  Note that glob28 will not be a pointer to
  2546. the Sys Name, but will rather contain the actual string data.
  2547.   51F0: 51C8 FFFC      20051EE          DBRA    D0,lho_3    This decrements D0 (the loop counter) and
  2548. branches back to the start of the loop until it is finished.
  2549.   51F4: 422D F4F5        -$B0B          CLR.B   glob27(A5)
  2550.   51F8: 267C 0000 028E    $28E          MOVEA.L #Rom85,A3    ROM85 is another of those variables that
  2551. my old IMs are missing so god only knows what is going on here.  I'll guess that it is looking for
  2552. the 128K roms.
  2553.   51FE: 4A53           'JS'             TST     (A3)
  2554.   5200: 6D20           2005222          BLT.S   lho_4
  2555.   5202: 42A7           'B.'             CLR.L   -(A7)
  2556.   5204: 3F3C 008F      '?<..'           PUSH    #143
  2557.   5208: 4EAD 00E2      1000AC6          JSR     proc38(A5)    Well, let's see here.  Proc38 uses the
  2558. passed parm as a trap number and returns that traps address on the stack.
  2559.   520C: 42A7           'B.'             CLR.L   -(A7)    Note that the trap address has not been
  2560. popped off the stack.  So when these next instructions are done, that address will still be on the
  2561. stack.
  2562.   520E: 3F3C 009F      '?<..'           PUSH    #159
  2563.   5212: 4EAD 00E2      1000AC6          JSR     proc38(A5)    Get another trap address on the stack,
  2564.   5216: 201F           ' .'             POP.L   D0    and put it in D0, leaving the first trap address
  2565. on the stack.
  2566.   5218: B09F           '..'             CMP.L   (A7)+,D0    Now, compare the two trap addresses,
  2567.   521A: 56C0           'V.'             SNE     D0    and set the low byte of D0 to FF hex if they are
  2568. not the same.
  2569.   521C: 4400           'D.'             NEG.B   D0    Do 2's complement - make the low byte of D0 its
  2570. own negative.  Since D0's byte is either 0 or FF (from the SNE), the NEG will make it either 0 (if it
  2571. was 0) or 1 (if it was FF) - (for NEG, invert the bits, then add a binary 1).
  2572.   521E: 1B40 F4F5        -$B0B          MOVE.B  D0,glob27(A5)    And save this number.
  2573.   5222: 42A7           'B.'    lho_4    CLR.L   -(A7)
  2574.   5224: 2F3C 0001 0000 '/<....'         PUSH.L  #$10000
  2575.   522A: 4EAD 009A      1000A5C          JSR     NewHandle(A5)    Get a new Handle for a block of size
  2576. 10000 hex.
  2577.   522E: 2B5F F4F0        -$B10          POP.L   glob26(A5)    And save the handle.
  2578.   5232: 6708           200523C          BEQ.S   lho_5    Branch if a NIL pointer (meaning the memory
  2579. was not available) is popped off the stack.
  2580.   5234: 487A FE26      200505C          PEA     MYGROWZO    Otherwise setup a grow zone function.
  2581.   5238: 4EAD 0092      1000A1E          JSR     SetGrowZone(A5)    A grow zone procedure is a custom
  2582. method for handling low memory conditions and overrides the memory managers routines.  Not a great
  2583. description, but we don't really care about this.
  2584.   523C: 4CDF 1880      'L...'  lho_5    MOVEM.L (A7)+,D7/A3-A4    Restore those saved regs,
  2585.   5240: 4E5E           'N^'             UNLK    A6    Kill the stack frame,
  2586.   5242: 4E75           'Nu'             RTS         And return to the caling proc.
  2587.  
  2588.  
  2589.   5244: D345 5455 5020 2020    data257  DNAME   SETUP   ,0
  2590.  
  2591.  
  2592.   524C: '..'                   data258  DC.W    8
  2593.  
  2594.                                ;-refs -  2/SETUP     
  2595.  
  2596.   524E: 4943                   data259  DC.B    'ICON'
  2597.  
  2598.                                ;-refs -  2/SETUP     
  2599.  
  2600.   5252: 5041                   data260  DC.B    'PACK'
  2601.  
  2602.  
  2603. The DRAWRESS Procedure
  2604.   1F6E:                                 QUAL    DRAWRESS ; b# =284  s#2  =proc148
  2605.  
  2606.                                vfp_1     VEQU  -256    One local variable.
  2607.                                param1    VEQU  8    One parameter needed.
  2608.   1F6E:                                 VEND    
  2609.  
  2610.                                ;-refs -  2/DRAWFHIN   2/SETUP      2/DRAWNUM   
  2611.                                ;-        2/DRAWDHIN  
  2612. OK, you should be able to just look at this and see what happens.  First off, look at the trap,
  2613. DrawString.  It takes one parameter, a pointer to a string.  Now, the previous line says to push the
  2614. address of the local variable so this has to be the string pointer.  Go back a few lines and we see
  2615. that proc5 is being called with two parameters: the string pointer, and the parameter from the
  2616. calling procedure.  You can deduce that proc5 has to get a string from somewhere, and probably will
  2617. call the GetString trap or some equivalent.  In fact, if you look at proc5, you will see that it
  2618. calls GetResource (resource type STR#).  This returns a handle to the STR# resource.  Proc5 then uses
  2619. the second parameter to figure out which string the calling procedure really wants.  Proc5 loops
  2620. through the STR# resource until it comes to the right string, then moves a pointer to the string into
  2621. the first parameter and returns.  When it gets back here, vfp_1 contains a pointer to the string.
  2622.   1F6E: 4E56 FF00      'NV..'  DRAWRESS LINK    A6,#-$100
  2623.   1F72: 486E FF00      200FF00          PEA     vfp_1(A6)
  2624.   1F76: 3F2E 0008      2000008          PUSH    param1(A6)
  2625.   1F7A: 4EAD 002A      100048C          JSR     proc5(A5)
  2626.   1F7E: 486E FF00      200FF00          PEA     vfp_1(A6)    At this point, vfp_1 has the stringptr.
  2627.   1F82: A884           '..'             _DrawString ; (s:Str255) 
  2628.   1F84: 4E5E           'N^'             UNLK    A6
  2629.   1F86: 205F           ' _'             POP.L   A0
  2630.   1F88: 544F           'TO'             ADDQ    #2,A7
  2631.   1F8A: 4ED0           'N.'             JMP     (A0)
  2632. Note that there is no RTS instruction to return.  The subroutine uses a common substitute.  First it
  2633. pops the return address off the stack (which is actually what the RTS would have done anyways) and
  2634. then does an indirect JMP (A0).  This just means to jump to whatever A0 points to and A0 points to
  2635. the return address.
  2636.  
  2637.   1F8C: C452 4157 5245 5353    data125  DNAME   DRAWRESS,0,0
  2638.  
  2639.  
  2640.  
  2641. The MAKEAWIN Procedure
  2642.  
  2643.   5852:                                 QUAL    MAKEAWIN ; b# =490  s#2  =proc209
  2644.  
  2645.                                vhy_1     VEQU  -12    Two local variables, no parms passed.
  2646.                                vhy_2     VEQU  -8
  2647.   5852:                                 VEND    
  2648.  
  2649.                                ;-refs -  1/DA Mover  
  2650.  
  2651.   5852: 4E56 FFF0      'NV..'  MAKEAWIN LINK    A6,#-$10
  2652.   5856: 42A7           'B.'             CLR.L   -(A7)    These instructions are setting up the
  2653. GetNewDialog below. 1st, clear space for the DialogPtr. 
  2654.   5858: 3F3C 000A      '?<..'           PUSH    #10    Push the Dialog ID #.
  2655.   585C: 42A7           'B.'             CLR.L   -(A7)    Push a NIL pointer for wStorage
  2656.   585E: 70FF           'p.'             MOVEQ   #-1,D0
  2657.   5860: 2F00           '/.'             PUSH.L  D0    Push a 32 bit -1 (IM says to do this to make the
  2658. dialog the frontmost window).
  2659.   5862: A97C           '.|'             _GetNewDialog ; (DlgID:INTEGER; wStorage:Ptr;
  2660. behind:WindowPtr):DialogPtr 
  2661.   5864: 2B5F FFFA           -6          POP.L   glob67(A5)    And pop off the dialogPtr.  This will be
  2662. used by proc MAKEBOX.
  2663.   5868: 486D FEC4        -$13C          PEA     glob48(A5)
  2664.   586C: 3F3C 000A      '?<..'           PUSH    #10    This is the dialog item - the left list box if
  2665. you check Resedit.
  2666.   5870: 4EBA FF32      20057A4          JSR     MAKEBOX    Well, after inspecting this procedure, it
  2667. looks like more can be determined by just looking at these few instructions here.  Notice that
  2668. MakeBox is being called with two parameters: The 1st being an unknown global variable, and the second
  2669. being one of the two list boxes in Mover's main dialog.  So it looks like MakeBox is just performing
  2670. some housekeeping on these two list boxes.
  2671.   5874: 486D FEC8        -$138          PEA     glob49(A5)
  2672.   5878: 3F3C 000B      '?<..'           PUSH    #11    Now do the right list box.
  2673.   587C: 4EBA FF26      20057A4          JSR     MAKEBOX
  2674.   5880: 206D FEC4        -$13C          MOVEA.L glob48(A5),A0    Get the address in (not of) glob48
  2675. into A0,
  2676.   5884: 2050           ' P'             MOVEA.L (A0),A0    and dereference it - or get whatever glob48
  2677. was pointing at into A0.
  2678.   5886: 216D FEC8 0004   -$138          MOVE.L  glob49(A5),4(A0)    Now move glob49 (a pointer I
  2679. suspect) into 4 past A0.  So glob48 contains a pointer which points four bytes behind the pointer in
  2680. glob49.
  2681.   588C: 206D FEC8        -$138          MOVEA.L glob49(A5),A0    Now do the exact opposite.  Grab the
  2682. pointer in glob49 and stick the pointer in glob48 4 bytes past it.
  2683.   5890: 2050           ' P'             MOVEA.L (A0),A0
  2684.   5892: 216D FEC4 0004   -$13C          MOVE.L  glob48(A5),4(A0)
  2685.  
  2686. These last few instructions were kind of a mess because we don't no anything about how globs 48 and
  2687. 49 will be used.  We will come back here after looking at MainEven and particularly HandleBu.  It
  2688. will turn out that these two globals are pointers (or maybe handles, we don't really care) to the two
  2689. list boxes on the main dialog.  In addition, each pointer as a way of referring to the other list
  2690. box.  At this point, this does not make any sense, but later on, glob 50 will be set to either glob48
  2691. or glob 49 (or NIL) depending on which list box - if any - has a selection made in it.  The reason
  2692. that glob48 and glob49 need to refer to each other, is that glob50 will be used to check both list
  2693. boxes to see if their associated volumes are locked.  See HandleBu for details.
  2694.   5898: 2F2D FFFA           -6          PUSH.L  glob67(A5)
  2695.   589C: 3F3C 0002      '?<..'           PUSH    #2    Item is the Copy button.
  2696.   58A0: 486E FFF4      200FFF4          PEA     vhy_1(A6)
  2697.   58A4: 486D FFF6          -$A          PEA     glob66(A5)    This will save a handle to it.
  2698.   58A8: 486E FFF8      200FFF8          PEA     vhy_2(A6)
  2699.   58AC: A98D           '..'             _GetDItem ; (dlg:DialogPtr; itemNo:INTEGER; VAR kind:INTEGER;
  2700. VAR item:Handle; VAR box:Rect) 
  2701.   58AE: 2F2D FFFA           -6          PUSH.L  glob67(A5)
  2702.   58B2: 3F3C 0006      '?<..'           PUSH    #6    Item is the left Open button.
  2703.   58B6: 486E FFF4      200FFF4          PEA     vhy_1(A6)
  2704.   58BA: 486D FFEC         -$14          PEA     glob63(A5)    This will save a handle to it.
  2705.   58BE: 486E FFF8      200FFF8          PEA     vhy_2(A6)
  2706.   58C2: A98D           '..'             _GetDItem ; (dlg:DialogPtr; itemNo:INTEGER; VAR kind:INTEGER;
  2707. VAR item:Handle; VAR box:Rect) 
  2708.   58C4: 2F2D FFFA           -6          PUSH.L  glob67(A5)
  2709.   58C8: 3F3C 0007      '?<..'           PUSH    #7    Item is the right Open button.
  2710.   58CC: 486E FFF4      200FFF4          PEA     vhy_1(A6)
  2711.   58D0: 486D FFF0         -$10          PEA     glob64(A5)    This will save a handle to it.
  2712.   58D4: 486E FFF8      200FFF8          PEA     vhy_2(A6)
  2713.   58D8: A98D           '..'             _GetDItem ; (dlg:DialogPtr; itemNo:INTEGER; VAR kind:INTEGER;
  2714. VAR item:Handle; VAR box:Rect) 
  2715. Now the program is going to assign dialog procedures to various of its items.  Items 12 and 13 - the
  2716. two filename boxes are assigned the DrawName proecdure.  Items 14 - the size selected box - gets
  2717. DrawSize.  Item 15 -the font text demo box - gets DrawHint.  Items 16 through 18 - various lines in
  2718. the dialog box - get DrawGray. And items 19 and 20 - the free space on disk boxes - get DrawFree.  If
  2719. you examine SetDProc, you will see that it simply invokes GetDItem to get a handle to the dialog item
  2720. (passed from the list below) and then uses SetDItem to set the dialogProcPtr to the procedure passed
  2721. from the list below.
  2722.   58DA: 3F3C 000C      '?<..'           PUSH    #12
  2723.   58DE: 487A FB2E      200540E          PEA     DRAWNAME
  2724.   58E2: 4EBA FE7E      2005762          JSR     SETDPROC
  2725.   58E6: 3F3C 000D      '?<..'           PUSH    #13
  2726.   58EA: 487A FB22      200540E          PEA     DRAWNAME
  2727.   58EE: 4EBA FE72      2005762          JSR     SETDPROC
  2728.   58F2: 3F3C 000E      '?<..'           PUSH    #14
  2729.   58F6: 487A FC32      200552A          PEA     DRAWSIZE
  2730.   58FA: 4EBA FE66      2005762          JSR     SETDPROC
  2731.   58FE: 3F3C 000F      '?<..'           PUSH    #15
  2732.   5902: 487A FA3A      200533E          PEA     DRAWHINT
  2733.   5906: 4EBA FE5A      2005762          JSR     SETDPROC
  2734.   590A: 3F3C 0010      '?<..'           PUSH    #16
  2735.   590E: 487A FE1C      200572C          PEA     DRAWGRAY
  2736.   5912: 4EBA FE4E      2005762          JSR     SETDPROC
  2737.   5916: 3F3C 0011      '?<..'           PUSH    #17
  2738.   591A: 487A FE10      200572C          PEA     DRAWGRAY
  2739.   591E: 4EBA FE42      2005762          JSR     SETDPROC
  2740.   5922: 3F3C 0012      '?<..'           PUSH    #18
  2741.   5926: 487A FE04      200572C          PEA     DRAWGRAY
  2742.   592A: 4EBA FE36      2005762          JSR     SETDPROC
  2743.   592E: 3F3C 0013      '?<..'           PUSH    #19
  2744.   5932: 487A FD12      2005646          PEA     DRAWFREE
  2745.   5936: 4EBA FE2A      2005762          JSR     SETDPROC
  2746.   593A: 3F3C 0014      '?<..'           PUSH    #20
  2747.   593E: 487A FD06      2005646          PEA     DRAWFREE
  2748.   5942: 4EBA FE1E      2005762          JSR     SETDPROC
  2749.   5946: 2F2D FFFA           -6          PUSH.L  glob67(A5)    Now the dialog is made the current Port
  2750.   594A: A873           '.s'             _SetPort ; (port:GrafPtr) 
  2751.   594C: 2F2D FFFA           -6          PUSH.L  glob67(A5)    and make the dialog visible,
  2752.   5950: A915           '..'             _ShowWindow ; (theWindow:WindowPtr) 
  2753.   5952: 2F2D FFFA           -6          PUSH.L  glob67(A5)    and make it the frontmost window.
  2754.   5956: A91F           '..'             _SelectWindow ; (theWindow:WindowPtr) 
  2755.   5958: 3F3C 0002      '?<..'           PUSH    #2
  2756.   595C: 4EBA A78A      20000E8          JSR     DIMITEM    These instructions dim the two Open buttons.
  2757.   5960: 3F3C 0003      '?<..'           PUSH    #3
  2758.   5964: 4EBA A782      20000E8          JSR     DIMITEM
  2759.   5968: 2F2D FFFA           -6          PUSH.L  glob67(A5)
  2760.   596C: A981           '..'             _DrawDialog ; (dlg:DialogPtr) And finally, draw the damn
  2761. thing.
  2762.   596E: 4E5E           'N^'             UNLK    A6
  2763.   5970: 4E75           'Nu'             RTS     
  2764.  
  2765.  
  2766.   5972: CD41 4B45 4157 494E    data270  DNAME   MAKEAWIN,0,0
  2767.  
  2768.  
  2769. The MAKEBOX Procedure.
  2770.   57A4:                                 QUAL    MAKEBOX ; b# =488  s#2  =proc208
  2771.  
  2772.                                vhx_1     VEQU  -14
  2773.                                vhx_2     VEQU  -10
  2774.                                vhx_3     VEQU  -8
  2775.                                vhx_4     VEQU  -4
  2776.                                param2    VEQU  8    Parm 2 is the dialog item #
  2777.                                param1    VEQU  10
  2778.   57A4:                                 VEND    
  2779.  
  2780.                                ;-refs -  2/MAKEAWIN  
  2781.  
  2782.   57A4: 4E56 FFF2      'NV..'  MAKEBOX  LINK    A6,#-$E
  2783.   57A8: 48E7 0018      'H...'           MOVEM.L A3-A4,-(A7)
  2784.   57AC: 266E 000A      200000A          MOVEA.L param1(A6),A3    A3 gets whatever is in parm 1.
  2785.   57B0: 2F2D FFFA           -6          PUSH.L  glob67(A5)    Push the DialogPtr,
  2786.   57B4: 3F2E 0008      2000008          PUSH    param2(A6)    And push the item #.
  2787.   57B8: 486E FFF6      200FFF6          PEA     vhx_2(A6)    This will get the Kind.
  2788.   57BC: 486E FFF2      200FFF2          PEA     vhx_1(A6)    This will get the ItemHandle.
  2789.   57C0: 486E FFF8      200FFF8          PEA     vhx_3(A6)    This will get the Box.
  2790.   57C4: A98D           '..'             _GetDItem ; (dlg:DialogPtr; itemNo:INTEGER; VAR kind:INTEGER;
  2791. VAR item:Handle; VAR box:Rect) 
  2792.   57C6: 2F2D FFFA           -6          PUSH.L  glob67(A5)    Now push the dialogPtr and item again...
  2793.   57CA: 3F2E 0008      2000008          PUSH    param2(A6)
  2794.   57CE: 3F2E FFF6      200FFF6          PUSH    vhx_2(A6)    Push the item Kind
  2795.   57D2: 487A F662      2004E36          PEA     DRAWBOX    See IM - this is a procPtr.
  2796.   57D6: 486E FFF8      200FFF8          PEA     vhx_3(A6)    And push the Box
  2797.   57DA: A98E           '..'             _SetDItem ; (dlg:DialogPtr; itemNo,kind:INTEGER; item:Handle;
  2798. box:Rect) 
  2799.   57DC: 42A7           'B.'             CLR.L   -(A7)
  2800.   57DE: 7064           'pd'             MOVEQ   #100,D0
  2801.   57E0: 2F00           '/.'             PUSH.L  D0
  2802.   57E2: 4EAD 009A      1000A5C          JSR     NewHandle(A5)
  2803.   57E6: 269F           '&.'             POP.L   (A3)    Get a new handle - size 100 - and put it into
  2804. parm1 (which A3 points to).
  2805.   57E8: 2053           ' S'             MOVEA.L (A3),A0    A0 gets the handle.
  2806.   57EA: 2850           '(P'             MOVEA.L (A0),A4    And A4 gets the pointer. OK, A0 is a handle
  2807. meaning it points to a pointer which in turn points to whatever it is we care about (in this case, a
  2808. free block of memory).  That means that (A0) grabs what ever A0 points to which is (by definition of
  2809. a handle) the pointer.
  2810.   57EC: 28AD FFFA           -6          MOVE.L  glob67(A5),(A4)    And now we put the dialogPtr into the
  2811. block of memory gotten by NewHandle.
  2812.   57F0: 426C 0060      'Bl.`'           CLR     96(A4)    Remember, A4 points (its a pointer, not a
  2813. handle!) to a block of memory, 100 bytes long.  So this instruction simply clears the 96 byte in that
  2814. block.
  2815.   57F4: 204C           ' L'             MOVEA.L A4,A0    Put the pointer into A0.
  2816.   57F6: 5088           'P.'             ADDQ.L  #8,A0    Add 8 to A0.  Previously we had stored the
  2817. dialogPtr at the beginning of this block.  Since a pointer is 8 bytes long, A0 no points to the first
  2818. byte after the dialogPtr.
  2819.   57F8: 43EE FFF8      200FFF8          LEA     vhx_3(A6),A1    vhx_3 is a Box which is of type Rect
  2820. which is 4 integers, or 4 words, or two long words.
  2821.   57FC: 20D9           ' .'             MOVE.L  (A1)+,(A0)+
  2822.   57FE: 20D9           ' .'             MOVE.L  (A1)+,(A0)+    So move the Box information into the free
  2823. memory right after the dialogPtr and increment A0 to the next free byte.
  2824.   5800: 302E FFFC      200FFFC          MOVE    vhx_4(A6),D0    This is tough since we don't know
  2825. what vhx_4 is to start with.
  2826.   5804: 906E FFF8      200FFF8          SUB     vhx_3(A6),D0    But whatever, subtrack vhx_3 from it,
  2827. result in D0.
  2828.   5808: 48C0           'H.'             EXT.L   D0    At this point, D0 is accurate to the word length
  2829. (since that was all the SUB specified).  This will make it's sign (negative or posative) accurate to
  2830. all 32 bits.
  2831.   580A: 81FC 0010      '....'           DIVS    #16,D0    Now, divide by 16.
  2832.   580E: 3940 0062      '9@.b'           MOVE    D0,98(A4)    And put this value (whatever it is) in
  2833. the last two bytes (notice it is a word length instruction) of the memory block.
  2834.   5812: 426C 0058      'Bl.X'           CLR     88(A4)
  2835.   5816: 397C FFFF 0056 '9|...V'         MOVE    #$FFFF,86(A4)
  2836.   581C: 422C 0014      'B,..'           CLR.B   20(A4)    These last instructions are filling in
  2837. various parts of the memory block.
  2838.   5820: 206D FFFA           -6          MOVEA.L glob67(A5),A0    Put the DialogPtr back in A0.
  2839.   5824: 2153 0098      '!S..'           MOVE.L  (A3),152(A0)    A3 still points to parm1.
  2840.   5828: 2F13           '/.'             PUSH.L  (A3)    So, this effectively pushes parm1
  2841.   582A: 4EBA AEA4      20006D0          JSR     MAKESBAR    This is fairly complicated, but this
  2842. procedure makes a scroll bar for the dialog item.
  2843.   582E: 2053           ' S'             MOVEA.L (A3),A0
  2844.   5830: 2050           ' P'             MOVEA.L (A0),A0    Can't tell what these instructions are doing.
  2845.   5832: 2068 0010      ' h..'           MOVEA.L 16(A0),A0
  2846.   5836: 2050           ' P'             MOVEA.L (A0),A0
  2847.   5838: 2153 0024      '!S.$'           MOVE.L  (A3),36(A0)
  2848.   583C: 4CDF 1800      'L...'           MOVEM.L (A7)+,A3-A4
  2849.   5840: 4E5E           'N^'             UNLK    A6
  2850.   5842: 205F           ' _'             POP.L   A0    Pop off the return address.
  2851.   5844: 5C4F           '\O'             ADDQ    #6,A7
  2852.   5846: 4ED0           'N.'             JMP     (A0)    And jump back to the calling procedure.
  2853.   5848: CD41 4B45 424F 5820    data269  DNAME   MAKEBOX ,0,0
  2854. The MAINEVEN Procedure
  2855. Basically, the main loop consists of a set of housekeeping routines, a call to ModalDialog to read
  2856. dialog events that take place, and a simple jump table to handle the various events.  D7 needs to be
  2857. zero for the loop to keep running.  If an error occurs, or the user hits Quit, D7 is changed to one
  2858. and the procedure exits.  First, DA Mover attempts to allocate a large block of memory (10000 hex)
  2859. into glob26.  If this is successful (or glob26 already has a memory handle) then the program skips
  2860. down to make some more checks - otherwise a memory error is generated.  Next, the procedure checks to
  2861. see if there are any files open and if so, calls FlushVol to write any changes to disk.
  2862.      0:                                 QUAL    MAINEVEN ; b# =1  s#1  =proc1
  2863.  
  2864.                                vab_1     VEQU  -6
  2865.      0:                                 VEND    
  2866.  
  2867.                                ;-refs -  1/DA Mover  
  2868.  
  2869.      0: 4E56 FFF8      'NV..'  MAINEVEN LINK    A6,#-8
  2870.      4: 48E7 0308      'H...'           MOVEM.L D6-D7/A4,-(A7)
  2871.      8: 4207           'B.'             CLR.B   D7    Enable the Main Event Loop.
  2872.      A: 4AAD F4F0        -$B10 lab_1    TST.L   glob26(A5)    glob46 will (or does) contain a handle to
  2873. a large block of memory.  So, if glob26 already has the handle, branch down, otherwise try to get
  2874. some memory.
  2875.      E: 661C           100002C          BNE.S   lab_2
  2876.     10: 42A7           'B.'             CLR.L   -(A7)    Clear stack space for the returned handle.
  2877.     12: 2F3C 0001 0000 '/<....'         PUSH.L  #$10000    Size of memory block needed.
  2878.     18: 4EBA 0A42      1000A5C          JSR     NewHandle
  2879.     1C: 2B5F F4F0        -$B10          POP.L   glob26(A5)    And get the handle in glob26.
  2880.     20: 660A           100002C          BNE.S   lab_2    Remember, a NIL handle or pointer is all
  2881. zeroes.  glob26 either has a valid handle or a NIL handle.  If it is valid, branch.
  2882.     22: 3F3C 0032      '?<.2'           PUSH    #50
  2883.     26: 4EAD 01CA      200023C          JSR     DOALERT(A5)    Otherwise do some memory alert (you can
  2884. check this if you like.)
  2885.     2A: 7E01           '~.'             MOVEQ   #1,D7    and disable the main event loop.
  2886.     2C: 1007           '..'    lab_2    MOVE.B  D7,D0
  2887.     2E: 6600 00D0      1000100          BNE     lab_15    Go if loop disabled from above.
  2888.     32: 206D FEC4        -$13C          MOVEA.L glob48(A5),A0    Get reference to left list box.
  2889.     36: 2850           '(P'             MOVEA.L (A0),A4
  2890.     38: 4A6C 0058      'Jl.X'           TST     88(A4)    Look at the descrpition of FlushVol (next
  2891. paragraph) to see what this variable means.
  2892.     3C: 670E           100004C          BEQ.S   lab_3    Seeing that 88(A4) is the VRefNum, then
  2893. branch if it is zero (no volume available - i.e. the list box has no opened file in it).
  2894.     3E: 4267           'Bg'             CLR     -(A7)    Space for function result (OSErr).
  2895.     40: 42A7           'B.'             CLR.L   -(A7)    iovNamePtr parameter (NIL).
  2896.     42: 3F2C 0058      '?,.X'           PUSH    88(A4)    iovRefNum parameter.
  2897.     46: 4EBA 0BAE      1000BF6          JSR     FlushVol    If a volume is available, flush it.
  2898.     4A: 3C1F           '<.'             POP     D6    Pop off error code.
  2899.  
  2900.     4C: 206D FEC8        -$138 lab_3    MOVEA.L glob49(A5),A0    Now do the same thing with the right
  2901. list box.
  2902.     50: 2850           '(P'             MOVEA.L (A0),A4
  2903.     52: 4A6C 0058      'Jl.X'           TST     88(A4)
  2904.     56: 670E           1000066          BEQ.S   lab_4
  2905.     58: 4267           'Bg'             CLR     -(A7)
  2906.     5A: 42A7           'B.'             CLR.L   -(A7)
  2907.     5C: 3F2C 0058      '?,.X'           PUSH    88(A4)
  2908.     60: 4EBA 0B94      1000BF6          JSR     FlushVol
  2909.     64: 3C1F           '<.'             POP     D6
  2910.  
  2911. Lets take a quick look and FlushVol and we can see a couple of things.  Fist of all, we can quickly
  2912. see what the parameters are:  Parm1 is a pointer to the Volume Name, Parm2 is the Volume Ref Number. 
  2913. Looking back at MainEven, we see that the PEA    88(A4) is referring to the Volume Reference Number. 
  2914. FlushVol "writes the contents of the associated volume buffer and descriptive informatin about the
  2915. volume (if they've changed since the last time FlushVol was called)." [IM II pg 89].  The returned
  2916. result of this procedure is the OSErr.
  2917.  
  2918.                               ;-refs -  1/MAINEVEN   2/FLUSHRES   2/REMOVEST  
  2919.  
  2920.    BF6: 4E56 FFC0      'NV..'  FlushVol LINK    A6,#-$40
  2921.    BFA: 41EE FFC0      200FFC0          LEA     vbu_1(A6),A0
  2922.    BFE: 316E 0008 0016 2000008          MOVE    param2(A6),ioVRefNum(A0)
  2923.    C04: 216E 000A 0012 200000A          MOVE.L  param1(A6),ioNamePtr(A0)
  2924.    C0A: A013           '..'             _FlushVol ; (A0|IOPB:ParamBlockRec):D0\OSErr 
  2925.    C0C: 3D40 000E      200000E          MOVE    D0,funRslt(A6)
  2926.    C10: 4E5E           'N^'             UNLK    A6
  2927.    C12: 225F           '"_'             POP.L   A1
  2928.    C14: 5C8F           '\.'             ADDQ.L  #6,A7
  2929.    C16: 4ED1           'N.'             JMP     (A1)
  2930.  
  2931.  
  2932. back to MainEven
  2933.  
  2934.     66: 4EAD 020A      2005DCA lab_4    JSR     HANDLEBU(A5)
  2935.     6A: 486D 0212      2005EF8          PEA     MYFILTER(A5)
  2936.     6E: 486E FFFA      200FFFA          PEA     vab_1(A6)
  2937.     72: A991           '..'             _ModalDialog ; (filterProc:ProcPtr; VAR itemHit:INTEGER) 
  2938. ModalDialog is the all-purpose dialog handler.  It will monitor events and wait for an event
  2939. involving an active dialog item.  Upon returning, the dialog item number is returned in ModalDialog's
  2940. 2nd parameter - in this case, vab_1.  Once the trap returns, the program has to figure out what to do
  2941. now that an item has been activated.  Below, is a simple jump table that repeatedly subtracts
  2942. integers from vab_1 until it is zero, at which point the program knows that it has the proper dialog
  2943. item.  It then branches to the appropriate routine.
  2944. ModalDialog also takes a parameter that specifies a special procedure that it can call whenever an
  2945. event occurs.  What that means, is that the line PEA   MYFILTER is telling ModalDialog to execute the
  2946. procedure MYFILTER anytime an event occurs.  We can take a look at MYFILTER to see what it is doing
  2947. (although in cracking, we probably don't care).  Right now I will guess that MYFILTER is taking care
  2948. of things like allowing multiple selections in the list boxes,. displaying the font string, and
  2949. displaying the size of the selection.
  2950.     74: 302E FFFA      200FFFA          MOVE    vab_1(A6),D0
  2951.     78: 5540           'U@'             SUBQ    #2,D0    Copy button.
  2952.     7A: 6736           10000B2          BEQ.S   lab_7
  2953.     7C: 5340           'S@'             SUBQ    #1,D0    Remove Button.
  2954.     7E: 672C           10000AC          BEQ.S   lab_6
  2955.     80: 5340           'S@'             SUBQ    #1,D0    Help Button.
  2956.     82: 6734           10000B8          BEQ.S   lab_8
  2957.     84: 5340           'S@'             SUBQ    #1,D0    Quit Button.
  2958.     86: 6720           10000A8          BEQ.S   lab_5
  2959.     88: 5340           'S@'             SUBQ    #1,D0    Left Open/Close Button.
  2960.     8A: 673C           10000C8          BEQ.S   lab_10
  2961.     8C: 5340           'S@'             SUBQ    #1,D0    Right Open/Close Button.
  2962.     8E: 6742           10000D2          BEQ.S   lab_11
  2963.     90: 5340           'S@'             SUBQ    #1,D0    Font Radio Button.
  2964.     92: 672A           10000BE          BEQ.S   lab_9
  2965.     94: 5340           'S@'             SUBQ    #1,D0    DA Radio Button.
  2966.     96: 6726           10000BE          BEQ.S   lab_9
  2967.     98: 5340           'S@'             SUBQ    #1,D0    Left List Box.
  2968.     9A: 6740           10000DC          BEQ.S   lab_12
  2969.     9C: 5340           'S@'             SUBQ    #1,D0    Right List Box.
  2970.     9E: 674A           10000EA          BEQ.S   lab_13
  2971.     A0: 0440 0028      '.@.('           SUBI    #40,D0    We will have to check MyFilter to see what
  2972. this is doing.
  2973.     A4: 6752           10000F8          BEQ.S   lab_14
  2974.     A6: 6058           1000100          BRA.S   lab_15
  2975.     A8: 7E01           '~.'    lab_5    MOVEQ   #1,D7    User hit Quit, so disable the loop and jump
  2976. to the loop end.
  2977.     AA: 6054           1000100          BRA.S   lab_15
  2978.     AC: 4EAD 01E2      2004E98 lab_6    JSR     REMOVEST(A5)    Remove Button.
  2979.     B0: 604E           1000100          BRA.S   lab_15
  2980.     B2: 4EAD 01EA      2004F5C lab_7    JSR     COPYSTUF(A5)    Copy Button.
  2981.     B6: 6048           1000100          BRA.S   lab_15
  2982.     B8: 4EAD 023A      2006B0E lab_8    JSR     DOHELP(A5)    Help Button.
  2983.     BC: 6042           1000100          BRA.S   lab_15
  2984.     BE: 3F2E FFFA      200FFFA lab_9    PUSH    vab_1(A6)    Push the selected item number,
  2985.     C2: 4EAD 022A      20064F2          JSR     SELCLICK(A5)    and change to either Fonts or DAs.
  2986.     C6: 6038           1000100          BRA.S   lab_15
  2987.     C8: 2F2D FEC4        -$13C lab_10   PUSH.L  glob48(A5)
  2988.     CC: 4EAD 0242      2006B50          JSR     DOCFILE(A5)    Left Open (or close) Button.
  2989.     D0: 602E           1000100          BRA.S   lab_15
  2990.     D2: 2F2D FEC8        -$138 lab_11   PUSH.L  glob49(A5)
  2991.     D6: 4EAD 0242      2006B50          JSR     DOCFILE(A5)    Right Open (or close) Button.
  2992.     DA: 6024           1000100          BRA.S   lab_15
  2993.     DC: 2F2D FEC4        -$13C lab_12   PUSH.L  glob48(A5)    Remember this guy?  Refers to the left
  2994. box.
  2995.     E0: 2F2D FFE8         -$18          PUSH.L  glob62(A5)
  2996.     E4: 4EAD 0202      2005CB8          JSR     CONTENTC(A5)    Handle a list box click.
  2997.     E8: 6016           1000100          BRA.S   lab_15
  2998.     EA: 2F2D FEC8        -$138 lab_13   PUSH.L  glob49(A5)    Refers to the right list box.
  2999.     EE: 2F2D FFE8         -$18          PUSH.L  glob62(A5)
  3000.     F2: 4EAD 0202      2005CB8          JSR     CONTENTC(A5)    List box handler.
  3001.     F6: 6008           1000100          BRA.S   lab_15
  3002.     F8: 3F2D FEDC        -$124 lab_14   PUSH    glob55(A5)
  3003.     FC: 4EAD 0232      2006A6A          JSR     HANDLEIN(A5)
  3004.    100: 1007           '..'    lab_15   MOVE.B  D7,D0    Here is the end of the main loop.  This
  3005. checks to see if the loop should terminate.  If not, branch back to the beginning of the loop.
  3006.    102: 6700 FF06      100000A          BEQ     lab_1
  3007.    106: 4CDF 10C0      'L...'           MOVEM.L (A7)+,D6-D7/A4    At this point, either an error
  3008. occurred or the user has hit the Quit button.
  3009.    10A: 4E5E           'N^'             UNLK    A6
  3010.    10C: 4E75           'Nu'             RTS     
  3011.  
  3012.    10E: CD41 494E 4556 454E    data1    DNAME   MAINEVEN,0,0
  3013. HANDLEBU Procedure
  3014.   5DCA:                                 QUAL    HANDLEBU ; b# =501  s#2  =proc214
  3015.  
  3016.                                vid_1     VEQU  -272
  3017.                                vid_2     VEQU  -256
  3018.   5DCA:                                 VEND    
  3019.  
  3020. A quick observation here.  After scanning the first few lines, you can notice some hereto unknown
  3021. things.  Look at the references to glob50.  At this point, we know that globs 48 and 49 have been set
  3022. up to refer (we don't know exactly how) to the two list boxes in the main dialog.  A quick look down
  3023. a ways reveals that D7 is used to pass an integer to our DrawString procedure (proc5).  If we assume
  3024. that D7 is the ID # of the STR# resource (since this is the parameter that proc5 requires), then that
  3025. MOVEQ 1,D7 (line 5) must refer to STR# 1 which reads "Copy".  The next two strings in the resource
  3026. are "<<Copy<<" and ">>Copy>>" which are exactly the three strings that the copy button on the dialog
  3027. can contain.  So we might assume right now that glob50 refers to one of the list boxes, and can be
  3028. used to determine whether the user has selected an item(s) in the list box.  Based upon this
  3029. information, the procedure will fill in the copy button with the proper string.
  3030.  
  3031.                                ;-refs -  1/MAINEVEN  
  3032.  
  3033.   5DCA: 4E56 FEEE      'NV..'  HANDLEBU LINK    A6,#-$112
  3034.   5DCE: 48E7 0308      'H...'           MOVEM.L D6-D7/A4,-(A7)
  3035.   5DD2: 4AAD FECC        -$134          TST.L   glob50(A5)    Check the list box (it seems)
  3036.   5DD6: 660C           2005DE4          BNE.S   lid_1    Look at what this branch is skipping.
  3037.   5DD8: 7E01           '~.'             MOVEQ   #1,D7    The string is "Copy".
  3038.   5DDA: 3F3C 0003      '?<..'           PUSH    #3    DIMITEM needs the item number to dim as a parm. 
  3039. Item 3 is the Remove button.
  3040.   5DDE: 4EBA A308      20000E8          JSR     DIMITEM    Take a quick look at DIMITEM and you will see
  3041. that it takes an item number as a parameter, pushes the parameter, then pushes the number -1 (255 if
  3042. we are talking about signed numbers) and calls HILITEIT which uses the 2nd parameter to either set or
  3043. dim the desired button.
  3044.   5DE2: 607A           2005E5E          BRA.S   lid_8    The Remove button is dimmed anytime there is
  3045. no selection in one of the list boxes.  How did this procedure know there was no selection?  It
  3046. checked to see if glob50 was blank (or possible a NIL pointer) and if so, there is no selection.
  3047.   5DE4: 202D FECC        -$134 lid_1    MOVE.L  glob50(A5),D0    Here is the real key.  glob50 is
  3048. being compared to glob48.  We know glob48 has something to do with the left list box, and look what
  3049. happens if they are the same...D7 gets 3 which means string">>Copy>>" - the user has made a selection
  3050. in the left list box.
  3051.   5DE8: B0AD FEC4        -$13C          CMP.L   glob48(A5),D0
  3052.   5DEC: 6604           2005DF2          BNE.S   lid_2
  3053.   5DEE: 7E03           '~.'             MOVEQ   #3,D7
  3054.   5DF0: 6002           2005DF4          BRA.S   lid_3
  3055.   5DF2: 7E02           '~.'    lid_2    MOVEQ   #2,D7    Otherwise the user has made a selection in
  3056. the right list box.  A quick note: glob50 was not compared to glob49, but it was compared to glob48. 
  3057. We can deduce from this that glob50 had to contain either glob48 or glob49. What this means is that
  3058. glob50 seems to indicate that something has been selected in one of the list boxes or is empty if
  3059. there is no selection.
  3060.   5DF4: 206D FECC        -$134 lid_3    MOVEA.L glob50(A5),A0    This is a mess. We know that glob50
  3061. is a handle to a host of information about one of the list boxes, but we didn't bother to figure
  3062. which bytes mean what.  The best thing to do here is to analyze all the branches in the mess, see
  3063. where they go, and look at what happens as a result of each branch.  So...
  3064.   5DF8: 2050           ' P'             MOVEA.L (A0),A0
  3065.   5DFA: 2068 0004      ' h..'           MOVEA.L 4(A0),A0
  3066.   5DFE: 2050           ' P'             MOVEA.L (A0),A0
  3067.   5E00: 3C28 0058      '<(.X'           MOVE    88(A0),D6    Look familiar?  Let's guess that this is
  3068. a vRefNum for the list box containing the selection.
  3069.   5E04: 206D FECC        -$134          MOVEA.L glob50(A5),A0
  3070.   5E08: 2050           ' P'             MOVEA.L (A0),A0
  3071.   5E0A: 2068 0004      ' h..'           MOVEA.L 4(A0),A0
  3072.   5E0E: 2050           ' P'             MOVEA.L (A0),A0
  3073.   5E10: 4A68 0056      'Jh.V'           TST     86(A0)
  3074.   5E14: 6C02           2005E18          BGE.S   lid_4    OK, here is a branch.  If it executes, D6 has
  3075. something (which we guessed to be a vRefNum) in it which gets passed on to lid_4.
  3076.   5E16: 4246           'BF'             CLR     D6    Otherewise, D6 is zeroed (no volume available).
  3077.   5E18: 4A46           'JF'    lid_4    TST     D6
  3078.   5E1A: 57C0           'W.'             SEQ     D0    D0=FF hex if there is no volume.
  3079.   5E1C: 4A00           'J.'             TST.B   D0
  3080.   5E1E: 6616           2005E36          BNE.S   lid_5    This branch executes if D6 was zero and will
  3081. cause 1 to moved into D7 - "Copy".
  3082.   5E20: 2F00           '/.'             PUSH.L  D0    Save D0 on the stack (not a parameter)
  3083.   5E22: 4267           'Bg'             CLR     -(A7)    Create space on the stack for the return
  3084. value.
  3085.   5E24: 3F06           '?.'             PUSH    D6    Aha!  We were right.  proc6 needs a vRefNum and
  3086. here is good old D6 being pushed as a parm.  D6 is indeed the vRefNum.
  3087.   5E26: 4EAD 0032      10004CA          JSR     proc6(A5)    Takes a vRefNum as a parm, then does a
  3088. GetVolInfo, and checks the iovAttributes to see if the disk is locked.  Returns a 1 if locked, 0 if
  3089. unlocked.
  3090.   5E2A: 121F           '..'             POP.B   D1    Pop off the locked status.
  3091.   5E2C: 201F           ' .'             POP.L   D0    Pop off the original D0.
  3092.   5E2E: 8001           '..'             OR.B    D1,D0    Or them so that, in effect, the AND
  3093. instruction below will be ANDing both D0 and D1 with 1.
  3094.   5E30: 0240 0001      '.@..'           ANDI    #1,D0    Check to see if one of the two contains a
  3095. non-zero value,
  3096.   5E34: 6702           2005E38          BEQ.S   lid_6    and if so, do not put a 1 in D7 (the string
  3097. is not "Copy").
  3098.   5E36: 7E01           '~.'    lid_5    MOVEQ   #1,D7    String is "Copy" (meaning that DA Mover will
  3099. not allow the Copy to proceed) and from the above code, we might guess that this is a result of the
  3100. destination volume being locked so copying is impossible.
  3101.   5E38: 4267           'Bg'    lid_6    CLR     -(A7)
  3102.   5E3A: 206D FECC        -$134          MOVEA.L glob50(A5),A0    And here is basically the same as
  3103. above except that the other list box's volume is being checked
  3104.   5E3E: 2050           ' P'             MOVEA.L (A0),A0
  3105.   5E40: 3F28 0058      '?(.X'           PUSH    88(A0)    Push the vRefNum of the volume from which the
  3106. selection has been made.
  3107.   5E44: 4EAD 0032      10004CA          JSR     proc6(A5)    Locked Volume?
  3108.   5E48: 101F           '..'             POP.B   D0
  3109.   5E4A: 670A           2005E56          BEQ.S   lid_7    Go if not locked.
  3110.   5E4C: 3F3C 0003      '?<..'           PUSH    #3    If the volume is locked, we cannot remove
  3111. anything so dim the Remove Button.
  3112.   5E50: 4EBA A296      20000E8          JSR     DIMITEM
  3113.   5E54: 6008           2005E5E          BRA.S   lid_8
  3114.   5E56: 3F3C 0003      '?<..'  lid_7    PUSH    #3    Else activate the Remove Button (volume is not
  3115. locked).
  3116.   5E5A: 4EBA A2AE      200010A          JSR     UNDIMITE
  3117.  
  3118. OK, let's re-cap for a minute.  If you look back at MakeAWin, you will note that glob48 and glob49
  3119. are set up to refer to information about the left and right list boxes respectively.  We also know
  3120. that these globs contain information about the volume (and possibly the file) that is being displayed
  3121. in the list boxes - since 88 bytes off the start of the pointer is the volume reference number.  The
  3122. above code can be broken  into two pieces: from line 5DF4, to lid_5 and from lid_6 to one line past
  3123. lid_7.  The first piece is messy, but the end result is that the destination volume is tested to see
  3124. if it is locked, and if so, the copy button text is set to "Copy".  Therefore we can now assume that
  3125. all that messy stuff beforehand was in essence setting a pointer to the destination list box
  3126. information.  Remember from MakeAWin there was a strange section of code that seemed to link the two
  3127. globs to each other?  Well, now we see that glob50 is set to one of these two (the one that contains
  3128. a selection) but glob50 must also be able to access the other list box's volume to see if it is
  3129. locked (or to see if copying to it is possible).  The second section checks to see if the volume
  3130. containing the selection is locked, and if so, Removing is not possible.
  3131.   5E5E: BE6D FFF4          -$C lid_8    CMP.W   glob65(A5),D7    Once again, we don't know what this
  3132. glob means, but we can see what gets skipped if the branch executes.  Once we know what gets skipped,
  3133. we have a decent idea what the global means.  Keep in mind that the global is being compared to D7 -
  3134. the string resource ID #.
  3135.   5E62: 6700 0082      2005EE6          BEQ     lid_13    So if glob65 contains the ID # in D7, skip to
  3136. the end of the procedure.
  3137.   5E66: 42A7           'B.'             CLR.L   -(A7)
  3138.   5E68: A8D8           '..'             _NewRgn ; :RgnHandle 
  3139.   5E6A: 285F           '(_'             POP.L   A4
  3140.   5E6C: 2F0C           '/.'             PUSH.L  A4
  3141.   5E6E: A87A           '.z'             _GetClip ; (rgn:RgnHandle) 
  3142.   5E70: 486E FEF0      200FEF0          PEA     vid_1(A6)
  3143.   5E74: 42A7           'B.'             CLR.L   -(A7)
  3144.   5E76: 42A7           'B.'             CLR.L   -(A7)
  3145.   5E78: A8A7           '..'             _SetRect ; (VAR r:Rect; left,top,right,bottom:INTEGER) 
  3146.   5E7A: 486E FEF0      200FEF0          PEA     vid_1(A6)
  3147.   5E7E: A87B           '.{'             _ClipRect ; (r:Rect) 
  3148.   5E80: 486E FF00      200FF00          PEA     vid_2(A6)
  3149.   5E84: 3F07           '?.'             PUSH    D7
  3150.   5E86: 4EAD 002A      100048C          JSR     proc5(A5)    Once again, the DrawString procedure.  D7
  3151. is the string # and vid_2 returns a pointer to the string.
  3152.   5E8A: 2F2D FFF6          -$A          PUSH.L  glob66(A5)    Look at the trap below.  glob66 HAS to be
  3153. a CtlHdl (Handle to a control object on a dialog),
  3154.   5E8E: 486E FF00      200FF00          PEA     vid_2(A6)    and vid_2 we already know has the string
  3155. whose ID # is in D7.  Since D7's string is "Copy", ">>Copy>>", or "<<Copy<<", we can assume that the
  3156. control in question is the Copy Button.
  3157.   5E92: A95F           '._'             _SetCTitle ; (Ctl:CtlHdl; title:Str255) 
  3158.  
  3159.   5E94: 3B47 FFF4          -$C          MOVE    D7,glob65(A5)    Here is a clue!  glob65 gets set to
  3160. the string ID# - now this makes sense.  Back up a few lines, glob65 was compared to D7 and if they
  3161. were equal, all this stuff gets skipped.  Now glob65 gets set to D7.  It looks like the program is
  3162. checking to see whether the Copy Button already has the correct string in it.  If not, the above code
  3163. changes it and updates glob65 to the new string ID# so that next time through the event loop, glob65
  3164. has the current ID # of the Copy Button's text.
  3165.   5E98: 7001           'p.'             MOVEQ   #1,D0
  3166.   5E9A: B047           '.G'             CMP.W   D7,D0    Remember: if D7 is 1, the string is "Copy",
  3167. and no copying is allowed - either because nothing is selected, or because the destination volume is
  3168. locked.
  3169.   5E9C: 660A           2005EA8          BNE.S   lid_9    If copying is to be allowed, then branch.
  3170.   5E9E: 3F3C 0002      '?<..'           PUSH    #2    Refers to the Copy Button:
  3171.   5EA2: 4EBA A266      200010A          JSR     UNDIMITE    and  - wait a second.  Notice that this
  3172. is backward!  It is dimming the copy button if copying is allowed!  I'm not sure why it does this,
  3173. but look down a few lines...
  3174.   5EA6: 6008           2005EB0          BRA.S   lid_10
  3175.   5EA8: 3F3C 0002      '?<..'  lid_9    PUSH    #2
  3176.   5EAC: 4EBA A23A      20000E8          JSR     DIMITEM
  3177.   5EB0: 2F0C           '/.'    lid_10   PUSH.L  A4
  3178.   5EB2: A879           '.y'             _SetClip ; (rgn:RgnHandle) 
  3179.   5EB4: 2F0C           '/.'             PUSH.L  A4
  3180.   5EB6: A8D9           '..'             _DisposRgn ; (rgn:RgnHandle) 
  3181.   5EB8: 7001           'p.'             MOVEQ   #1,D0    Here we go.  Now, if D7 is 1, dim the copy
  3182. button, otherwise enable it.
  3183.   5EBA: B047           '.G'             CMP.W   D7,D0
  3184.   5EBC: 660A           2005EC8          BNE.S   lid_11
  3185.   5EBE: 3F3C 0002      '?<..'           PUSH    #2
  3186.   5EC2: 4EBA A224      20000E8          JSR     DIMITEM
  3187.   5EC6: 6008           2005ED0          BRA.S   lid_12
  3188.   5EC8: 3F3C 0002      '?<..'  lid_11   PUSH    #2
  3189.   5ECC: 4EBA A23C      200010A          JSR     UNDIMITE
  3190.   5ED0: 206D FFF6          -$A lid_12   MOVEA.L glob66(A5),A0    We already saw (from the SetCTitle
  3191. trap above) that glob66 is a handle to the Copy button.
  3192.   5ED4: 2050           ' P'             MOVEA.L (A0),A0    Convert the handle to a pointer.
  3193.   5ED6: 43EE FEF0      200FEF0          LEA     vid_1(A6),A1
  3194.   5EDA: 5088           'P.'             ADDQ.L  #8,A0    Well, according to IM, adding 8 bytes to a
  3195. pointer to a control record makes the pointer point to the a window that the control is in.
  3196.   5EDC: 22D8           '".'             MOVE.L  (A0)+,(A1)+    So, move the WindowPtr to vid_1.
  3197.   5EDE: 22D8           '".'             MOVE.L  (A0)+,(A1)+    and now move the Rect (next parameter in
  3198. a control record) into vid_1.
  3199.   5EE0: 486E FEF0      200FEF0          PEA     vid_1(A6)
  3200.   5EE4: A92A           '.*'             _ValidRect ; (goodRect:Rect)     This trap tells the Window
  3201. Manager not to update the region Rect.
  3202.   5EE6: 4CDF 10C0      'L...'  lid_13   MOVEM.L (A7)+,D6-D7/A4    And, now we are finished.
  3203.   5EEA: 4E5E           'N^'             UNLK    A6
  3204.   5EEC: 4E75           'Nu'             RTS     
  3205.  
  3206. I am not sure exactly what is going on there when it sets the button to the opposite that it is
  3207. supposed to be, then sets it properly.  I might hazard a guess that this technique somehow gurrantees
  3208. that the region will get redrawn properly, but I really don't know - nor do I really care, for that
  3209. matter.  It is pretty clear what this procedure does - it updates the text and active status of the
  3210. various buttons on the main dialog.  Once this is done, MainEven can let the user make a selection,
  3211. act upon the selection, and then the whole thing starts over.
  3212.  
  3213.   5EEE: C841 4E44 4C45 4255    data276  DNAME   HANDLEBU,0,0
  3214.  
  3215. Well, that wraps up the intensive assembly listing.  Font/DA Mover has many more procedures, but the
  3216. idea here was to look at an assembly listing and apply the stuff at the beginning of the tutorial to
  3217. a real life situation and see if you can guess what is going on.  Next I will discuss the use of
  3218. TMON, and finally we will look at cracking a real application:  Sorcerer.  (I am choosing this
  3219. because it is easy, and I recently cracked it so it is still failry fresh in my mind.)
  3220.  
  3221. Using TMON
  3222.  
  3223. TMON, unlike Nosy, is a real-time monitor / debugger.  We will be using TMON in several situations:
  3224. to break into active dialog windows, to break into programs that Nosy won't decompile properly, or
  3225. when Nosy produces such a massive listing that we need to trace the application to see what happens
  3226. where.  To install TMON, just drag the application and the init into the system folder and restart. 
  3227. The application can be launched to configure it, but you probably won't need to do this.  If you do
  3228. configure it, make sure you save the changes in a User Area in the System Folder.
  3229. TMON can be entered several ways: System Errors, Debugger traps (this is a great technique for
  3230. breaking into tough programs), user specified traps, and by pressing the interrupt button on the side
  3231. of your Mac.  If you lack the interrupt button, use the Programmer's Key init - this allows you to
  3232. hold down command and option and press the startup key on an extended keyboard.
  3233. Once in TMON, you are presented with a Menu bar and possibly some windows.  A quick note about TMON
  3234. windows.  They can be resized and dragged only in the vertical directions.  To change values in the
  3235. various windows, click the insertion bar in front of the value to change and type right over the old
  3236. value.  Pressing Return chops off the line at the insertion bar, pressing Enter leaves the rest of
  3237. the line as is.  For example, lets say you are changing the address of a dump window.  If it
  3238. currently reads "Dump From 00000000" and you type 1234 over the first 4 values, you have two choices. 
  3239. Hitting Return at this point chops off the last 4 zeroes making the effective address 1234 hex.  If
  3240. you were to hit Enter instead, the remaining zeroes would remain making the effective address
  3241. 12340000 hex.  Here are what the various menu commands do:
  3242. Dump / Cmd-d  and Asmbly / Cmd-a
  3243. Brings up either a dump window or an assembly window.  The dump window lists hex and ascii codes for
  3244. a block of memory and the assembly window disassembles memory.  The first line allows you to specify
  3245. where the window will start its listing: Dump (Assembly) From  XXXXXXX where XXXXXXX is an effective
  3246. address.  You can move the insertion bar right into this line and type over whatever is there.  You
  3247. can enter an address directly, specify a register (and the window will start from the address
  3248. contained in the register), or a register indirect (the window will start from the address in the
  3249. register, but will remember the register address).  Examples:  Dump From:
  3250.     1)    80FFCA    Dump listing starts from the absolute address 80FFCA hex.  If you scroll the window,
  3251. the displayed address will change to the address of the first line in the listing.
  3252.     )2    A5        Dump starts from the address contained in register A5.  The address displayed on the
  3253. Dump From line will be replaced with the address in register A5.  If you scroll, the displayed
  3254. address will again change to reflect the first line in the listing, and if A5 changes, the window
  3255. will not change.
  3256.     3)    0(A1)        Dump starts from the address in A1 plus zero (in this case).  The displayed
  3257. address on the Dump From line does not change to the address in A1, rather it now displays
  3258. 00000000(A1) indicating that the listing is anchored to the register.  As you scroll, the zeroes will
  3259. change to reflect how many bytes from the address in A1 the first line in the listing is - also, if
  3260. A1 changes, the window will automatically change to the new value of A1.
  3261. The most common entry for an assembly window is 0(PC) which says to disassemble from the program
  3262. counter.  Then as you step through the program, the window automatically scrolls so that the first
  3263. line is where the program counter is.  The windows list - from left to right - the address, any
  3264. registers that contain that address (Note the P - for program counter - next to the first line when
  3265. you disassemble from 0(PC) ), the resource the listing comes from if any (assembly window only), and
  3266. then either hex and ascii bytes, or disassembled instructions.  In addition, the assembly window will
  3267. display comments to the right, indicating the destination of branches.  Additional dump windows can
  3268. be activated by holding down Shift while clicking on Dump in the menu bar - this is the only display
  3269. that can have multiple windows.  You will find if handy to have, in addition to the dissambly window,
  3270. a dump window anchored to the A7 register (so make the Dump From read 0(A7) ) so that you can quickly
  3271. see what addresses are being pushed on the stack.  If you need to see what the actual data of these
  3272. addresses are, just shift-click Dump to bring up successive dump windows, and make each window dump
  3273. from successive addressess (4 bytes each) on the stack.  Remember that the stack moves backwards, so
  3274. the first thing pushed on the stack will be to the right (in the dump window) of the second thing
  3275. pushed on the stack, etc.
  3276. Brkpts / Cmd-b
  3277. Allows the setting of up to eight breakpoints.  Simply enter the address of the breakpoint into one
  3278. of the 8 slots.  To remove a breakpoint, type a hyphen for the first digit of the address to remove
  3279. and hit return.  Breakpoints cause TMON to halt execution of the application at the address of the
  3280. breakpoint.  I generally use breakpoints to skip out of long loops.  For example, if you are stepping
  3281. through a section of code and you find a DBRA loop (usually moving a section of data) where the data
  3282. register has some god-awful value like 63 (often used to move strings), enter a breakpoint at the
  3283. address of the instruction immediately after the DBRA and then exit.  TMON will break execution after
  3284. the loop has finished.
  3285. Regs / Cmd-r
  3286. Displays the 16 registers, PC, and status flags, any of which can be modified by typing right over
  3287. the current values.  The flags are displayed as the letter that I have been using - C for Carry, Z
  3288. for Zero, etc.  When the letter is capitalized, the flag is set.  To change the value of the flag,
  3289. simply change the capitalization.
  3290. Heap / Cmd-h
  3291. Displays memory blocks in the application heap zone.  Basically this window lists all allocated
  3292. blocks of memory in the applications heap zone (in the form of the pointers to the blocks), the size
  3293. of the block, a digit that is meaningless to me, and the blocks status - either 1) Free, not
  3294. allocated to anything yet, 2) Nonrel, non-relocatable, 3) Handle at ...., relocatable block with
  3295. handle at the address specified, or 4) INVALID which means there is a big problem somewhere.
  3296. File / Cmd-f
  3297. Brings up a window listing all open resource files by file reference number.  In most cases, the last
  3298. number in the list refers to the System File.  Entering a file reference number after the Resource
  3299. file # prompt lists the files resources and where in memory they are.  From left to right, the
  3300. information displayed is: Resource type, Resource ID #, Attributes, location in memory.  Attributes
  3301. are as follows: R = System reference, H = Load into system heap, P = purgeable, L = locked, T =
  3302. protected, 1 = pre-loaded (loaded at startup time), W = write into resource file.  To return to a
  3303. list of file reference numbers, click the insertion bar before the file number you previously typed
  3304. in and hit return.
  3305. Exit / Cmd-e
  3306. Returns control to the Mac.  Execution starts from the current value (which can be modified, of
  3307. course, via the Regs window).
  3308. Gosub / Cmd-g
  3309. Same as Step (below), except that all JSR and BSR instructions are treated as a single instruction
  3310. and the subroutine is called invisibly to you.  In other words, this command executes exactly as if
  3311. you had set a breakpoint immediately after the JSR or BSR and then exited.  I often use this command
  3312. the first time through a program to quickly find which JSR calls the subroutine that bombs.  If you
  3313. look at the Font/DA Mover listing above and condsider the Da Mover portion, imagine this as a
  3314. protected program that Nosy won't handle.  You are presented with several subroutines which you
  3315. certainly don't want to spend valuable time tracing.  So, you Gosub each one until you get a bomb. 
  3316. Then you know which one you need to spend time tracing.
  3317.  
  3318. Step / Cmd-s
  3319. Executes the instruction pointed to by the PC.  This command allows you to execute a program one
  3320. instruction at a time with one limitation (or boon) which is that traps are executed as if they were
  3321. a single instruction.  Use the Trace command to step through the actual ROM trap code.  All windows
  3322. that are affected by the executed instruction are updated automatically.
  3323. Trace / Cmd-t
  3324. Same as Step, except that ROM traps will be followed into their ROM code.  You will never need to do
  3325. this to crack a program, however if you want to see what a trap is really doing, use this command.
  3326. Num / Cmd-n
  3327. Brings up TMON's calculator.  Any expression (almost) will be evaluated and displayed.  For example,
  3328. entering a trap name will return the trap number; entering a mathematical expression (or a number)
  3329. will return the result in hex and decimal, etc.  There are a million variations on this, non of which
  3330. I have ever used, so if you have a question, get in touch with me for more info.
  3331. User / Cmd-u
  3332. This has a wealth of handy commands, but my desctiptions my descriptions will be limited to commands
  3333. that I have used.  There are three different screens associated with the User window: A000 trap
  3334. functions, Control functions, and Memory functions.  To switch pages, click on the line that reads
  3335. Toggle Pages and press return until you arrive at the page you desire.
  3336.     Control Functions:
  3337. Look for labels:    Unknown.
  3338. Label table    Unknown.
  3339. Label add/remove    Unknown.
  3340. Label file load    Unknown.
  3341. Registers    Unknown.  Has something to do with TMON's internal registers.
  3342. Leave TMON: queue...    Similar to Exit, except that TMON will trap out all events and regain control
  3343. when you click the mouse.  When TMON regains control, the previously generated events will be
  3344. available in the event queue.  To activate this function, click on the Leave TMON... line and press
  3345. Return.
  3346. Leave application...    Use this function when your application system bombs.  Using 0 as a
  3347. parameter, attempts to quit to the active shell (usually the Finder), using 1 will attempt to
  3348. re-launch the program.  If you are in a program (not necessarily one you are cracking) and it system
  3349. bombs, you will dive into the monitor.  Use this function with a parameter of 0 and usually the app
  3350. will quit to the Finder leaving any other open applications running normally.
  3351. Shut Down    If the above does not gracefully exit to the Finder, you may need to use this function. 
  3352. The higher the number of the parameter you use,  the safer your shutdown will be.  If you have to
  3353. resort to 0 (re-boot), you will have the long wait for boot up associated with turning the computer
  3354. off then on.
  3355.     Memory Functions:
  3356. Block Move    Moves blocks of memory.  Requires three parameters: source address, destination address,
  3357. and length.  Enter these three address after one another on the line and hit return.
  3358. Block Compare    Compares blocks of memory using the same three parameters as the Block Move command. 
  3359. Any differences will be displayed as "Mismatch at xxxx/yyyy" where xxxx is the address of the source
  3360. and yyyy is the address of the destination where the blocks do not match.
  3361. Fill    Fills a block of memory with a specified value.  Takes four parametes with the fourth being
  3362. optional: beginning address, ending address, fill value, and optionally, the size of the fill value -
  3363. 1 for byte fill, 2 for word fill, and 4 for long word fill.
  3364. Find    Finds a specified value in a specified range of memory.  Takes four parameters: search value,
  3365. search value size (same as size from Fill command above), start address and end address.  If any
  3366. matches are found, they will be displayed between the curly braces.
  3367. Template    Displays a memory location as if it were a Mac data structure, showing you all the
  3368. current values.  TMON currently knows only four data structures: WindowRecord, ControlRecord,
  3369. TERecord, and ParamBlock (see IM for descriptions of these).  Clicking on the Template line hitting
  3370. Return will cycle through these four templates.  Template takes one parameter, an address.  So, after
  3371. finding the structure you wish to display, enter an address that contains a structure of that type
  3372. and hit return.  TMON will list all current values for the fields of that structure.  Note that
  3373. information will be meaningless unless there is actually a structure of the desired type at the
  3374. address you specify.  This command could be helpful in looking at key disk checkers by allowing you
  3375. to look at the ParamBlock the program is currently using to read the disk - although I have never
  3376. used this.
  3377. Stack addresses    Attempts to recognize as labels the supplied address.  This function defaults to an
  3378. address of SP - stack pointer.  To use this, just click to left of SP and hit return.  The function
  3379. will then look at the first address on the stack and see if it matches any labels that it currently
  3380. knows.  For example, right after a JSR, the stack contains the return address.  If TMON k knows a
  3381. label for the return address (and it will if there was a label to the left of the JSR in the assembly
  3382. window) then using the Stack Addresses command will display the label in curly braces.  Hitting
  3383. return repeatedly will then move up the stack, analysing each successive stack address.  Click in
  3384. front of the SP and hit return to reset the command to the original stack pointer.
  3385. Stack crawl    Attempts to find the return address of a procedure that has a currently active stack
  3386. frame.  Remember that most compiled programs use the LINK and UNLK instructions to set up stack
  3387. frames to temprarily store local variables.  If you know what register is being used as the stack
  3388. frame pointer (A6 is the only one I have ever seen and this is the default value TMON uses), then the
  3389. Stack Crawl can use that register to analyse the stack and try to determine the return address and
  3390. display it in the curly braces.
  3391. Load resource    Loades the resource specified by the two parameters (type and id #) into memory and
  3392. displays the address of the resource in the curly braces.
  3393. Print    Allows you to print listings longer that contained in the active window.  Clicking on the
  3394. Print line and hitting return toggles the print mode between Dump, Assembly, File, and Heap.  Once
  3395. the mode has been selected, the print command needs a start and end address.  Type these in, hit
  3396. return, and TMON will print the desired output to the serial port (meaning that you cannot use a
  3397. laserwriter, but you can use an imagewriter.)
  3398.     A000 Trap Functions:
  3399. Trap record    Unknown.  Allows you to record any traps called by the program, but requires a lot of
  3400. complicated set up.
  3401. Record    Unknown.  Used to allocate a table for trap record (above).
  3402. Trap    Unknown.  Used by programmers to test the heap anytime a trap that affects the heap zone is
  3403. called.  We don't need this to crack.
  3404. Heap    Unknown.  Similar to Trap but doesn't wait for a trap to execute.  We don't need this one
  3405. either.
  3406. Trap discipline    A programmer's feature.  Trap discipline is a means of checking traps for faulty
  3407. parameters.  Select a range of traps and a PC range (see Trap Intercept below) and TMON will check
  3408. all traps within that range.  If it finds a trap with questionable parameters, the monitor will be
  3409. entered.  There are two strengths of discipline: lenient and strict.  To toggle these, click on the
  3410. trap discipline line and hit return.
  3411. Trap checksum    Unknown.  Another function that programmers would use to check application problems. 
  3412. Since we are cracking an application that already works, we don't need this one.
  3413. Checksum    Unknown.  Used to specify the checksum for Trap Checksum.
  3414. Trap intercept    Allows you to specify a trap or range of traps that, when encountered, will cause the
  3415. monitor to be entered.  Simply click on the line and enter the trap name WITH a leading underscore, a
  3416. space, and then the second trap.  This specifies a range of traps to look for, the range being in
  3417. numerical order of trap numbers.  If only one trap is specified, only that trap will be checked.  Use
  3418. this to catch a program that uses a dialog to prompt for a serial number.  If the trap entered is
  3419. _ModalDialog, the monitor will be entered just before the dialog is drawn.  Optionally, a PC range
  3420. may be entered after the trap range.  This would specify that TMON regain control only if the
  3421. specified trap is encountered within the specified PC range.  I have never used a PC range.
  3422. Trap signal    Similar to Trap Interrupt, except that once the trap range and optional PC range have
  3423. been entered, the user must hit the interrupt switch to enter the monitor.  Once the interrupt switch
  3424. (or Programmer's Key) has been pressed, TMON will continue execution until a trap within the
  3425. specified range has been encountered.
  3426. Options / Cmd-o
  3427. Allows setting of seven monitor global functions.  I am not exactly clear what the various settings
  3428. mean, so I jus leave them all on.
  3429. Print / Cmd-p
  3430. Causes the active window to be dumped to whatever port has been set during setup (achieved by
  3431. launching the TMON application).  This prints a window's contents only!  To get long printouts, use
  3432. the print command in the User Window.
  3433.  
  3434.  
  3435. How to crack Sorcerer
  3436. We are now going to look at a typical key-disk protection scheme.  The important concepts to grasp
  3437. here are how to quickly isolate the protection, and then how to remove it.  Don't worry too much
  3438. about the particulars, unless you happen to have a copy of Sorcerer you want to crack.
  3439. First off, how do we know that it is protected?  Dumb question, but this is really important to
  3440. beginning the crack.  With Sorcerer, we note that when launched from the hard drive, it brings up a
  3441. dialog box (or alert) requesting the key disk.  So the logical place to start is with Resedit to try
  3442. and figure out what resource the program is using to display the alert.
  3443. After you open the application in Resedit, we see the following:
  3444. 
  3445. Well, there are no ALRT or DLOG resources, so the program is generating its own dialog internally. 
  3446. If there was a set of ALRT or DLOG resources, we would quickly scan them and try to determine which
  3447. was the one that the program displays to request the key-disk.  If we could locate the ID # of the
  3448. correct DLOG resource, we would go into Nosy and bring up the Traps ref map, see which procs called
  3449. GetNewDialog, or Alert (if the resource in question was ALRT), and then check all the procs Nosy
  3450. listed to see which one called GetNewDialog with the ID # we had found in Resedit.
  3451. Often you will find that there are DLOGs or ALRTs, but none of them have the correct message.  If
  3452. this is the case, then we would be in the same spot we are right now.  The next thing to consider is
  3453. that the string "Please Insert the Original Disk" (or whatever the string is) has to come from
  3454. somewhere.  You can try to locate it in Nosy, but often the string will be in a string resource. 
  3455. Look at the Resedit window above, and note the STR resource.  Let's take a look:
  3456. Perfect!  There is the culprit.  So, all we have to do is find the part of Sorcerer that uses STR
  3457. resource # 256.  Since there are several ways to load a string, you might want to forget the Traps
  3458. ref map and start tracing the program.  If the program is huge, this might not be the way to go.  If
  3459. you look at the Traps ref map for Sorcerer, you would eventually find that proc108 calls the trap
  3460. GetString.  This would be an excellent place to start.  Otherwise you might just find the proc called
  3461. Sorcerer and start tracing there...An important note:  tracing programs from start to error sucks. 
  3462. If you can figure out which trap is causing the problem, then by all means do so.  If you are not
  3463. familiar enough with the various traps, then you might well have to trace.  Get a hold of IM and
  3464. learn the Dialog Manager and the Resource Manager!
  3465.  
  3466. OK, let's start with the procedure Sorcerer:
  3467.  
  3468.    D50:                                 QUAL    Sorcerer ; b# =59  s#1  =proc38
  3469.  
  3470.  
  3471.    D50: 4EBA 004C      1000D9E Sorcerer JSR     proc39
  3472.    D54: 4E56 0000      'NV..'           LINK    A6,#0
  3473.    D58: 2C5F           ',_'             POP.L   A6
  3474.    D5A: 4E55 FCB6      'NU..'           LINK    A5,#-$34A
  3475.    D5E: 9FED 0010          $10          SUBA.L  glob27(A5),A7
  3476.    D62: 4EBA 0042      1000DA6          JSR     proc41
  3477.    D66: 41ED FCB2        -$34E          LEA     glob2(A5),A0
  3478.    D6A: 2F08           '/.'             PUSH.L  A0
  3479.    D6C: 4EBA F292      1000000          JSR     proc1
  3480.    D70: A8FE           '..'             _InitFonts  
  3481.    D72: 3F3C FFFF      '?<..'           PUSH    #$FFFF
  3482.    D76: 4267           'Bg'             CLR     -(A7)
  3483.    D78: 4EBA F49A      1000214          JSR     FlushEvents
  3484.    D7C: A912           '..'             _InitWindows  
  3485.    D7E: A9CC           '..'             _TeInit  
  3486.    D80: 42A7           'B.'             CLR.L   -(A7)
  3487.    D82: A97B           '.{'             _InitDialogs ; (resumeProc:ProcPtr) 
  3488.    D84: A850           '.P'             _InitCursor  
  3489.    D86: 4EAD 0092      20003F6          JSR     proc108(A5)
  3490.    D8A: 4EBA 0390      100111C          JSR     proc54
  3491.    D8E: 4EBA 0156      1000EE6          JSR     %_TERM
  3492.    D92: 4E5D           'N]'             UNLK    A5
  3493.    D94: 4EBA 000E      1000DA4          JSR     proc40
  3494.    D98: 4E75           'Nu'             RTS     
  3495.  
  3496.  
  3497.    D9A: 4E5E                   data20   DC.B    'N^Nu'
  3498.  
  3499. A quick scan should reveal that possible problem areas are proc39, proc41, proc1, proc108, and proc54
  3500. since these are procedures that we can't see from this listing which is normal enough by itself. 
  3501. Luckily, if you were to look at the first three procs called, they are very short and very benign. 
  3502. If these were long, complex procedures, I might seriously consider going into TMON and setting a Trap
  3503. Intercept to pick up _InitFonts so that TMON would grab control of the program early.  Then when I
  3504. launch Sorcerer, if TMON breaks in then the error is later in the program, but if Sorcerer bombs,
  3505. then the error was before the InitFonts.  That is a quick way to locate the problem.
  3506.  
  3507. So, let's take a look at the next procedure, proc108:
  3508.  
  3509.    3F6:                                 QUAL    proc108 ; b# =194  s#2  =proc108
  3510.  
  3511.                                vem_1     VEQU  -1040
  3512.                                vem_2     VEQU  -1038
  3513.                                vem_3     VEQU  -1036
  3514.                                vem_4     VEQU  -1034
  3515.                                vem_5     VEQU  -1030
  3516.                                vem_6     VEQU  -774
  3517.                                vem_7     VEQU  -512
  3518.    3F6:                                 VEND    
  3519.  
  3520.                                ;-refs -  1/proc37     1/Sorcerer  
  3521.  
  3522.    3F6: 4A6F EBE6      'Jo..'  proc108  TST     -$141A(A7)
  3523.    3FA: 4E56 FBE6      'NV..'           LINK    A6,#-$41A
  3524.    3FE: 48E7 0F18      'H...'           MOVEM.L D4-D7/A3-A4,-(A7)
  3525.    402: 41EE FE00      200FE00          LEA     vem_7(A6),A0
  3526.    406: 2848           '(H'             MOVEA.L A0,A4
  3527.    408: 486E FBFA      200FBFA          PEA     vem_5(A6)
  3528.    40C: 486E FBF0      200FBF0          PEA     vem_1(A6)
  3529.    410: 486E FBF6      200FBF6          PEA     vem_4(A6)
  3530.    414: A9F5           '..'             _GetAppParms ; (VAR apName:Str255; VAR apRefNum:INTEGER; VAR
  3531. apParam:Handle) 
  3532.    416: 4267           'Bg'             CLR     -(A7)
  3533.    418: 41EE FCFA      200FCFA          LEA     vem_6(A6),A0
  3534.    41C: 2F08           '/.'             PUSH.L  A0
  3535.    41E: 486E FBF2      200FBF2          PEA     vem_2(A6)
  3536.    422: 4EAD 0052      1000162          JSR     GetVol(A5)
  3537.    426: 3E1F           '>.'             POP     D7
  3538.    428: 4267           'Bg'             CLR     -(A7)
  3539.    42A: 486E FBFA      200FBFA          PEA     vem_5(A6)
  3540.    42E: 3F2E FBF2      200FBF2          PUSH    vem_2(A6)
  3541.    432: 3F3C 0010      '?<..'           PUSH    #16
  3542.    436: 2F0C           '/.'             PUSH.L  A4
  3543.    438: 4267           'Bg'             CLR     -(A7)
  3544.    43A: 4EBA FDBE      20001FA          JSR     proc103
  3545.    43E: 181F           '..'             POP.B   D4
  3546.    440: 4267           'Bg'             CLR     -(A7)
  3547.    442: 3F2E FBF2      200FBF2          PUSH    vem_2(A6)
  3548.    446: 2F0C           '/.'             PUSH.L  A4
  3549.    448: 4EBA FED8      2000322          JSR     proc105
  3550.    44C: 101F           '..'             POP.B   D0
  3551.    44E: 0A00 0001      '....'           EORI.B  #1,D0
  3552.    452: 6700 00A0      20004F4          BEQ     lem_2
  3553.    456: 4267           'Bg'             CLR     -(A7)
  3554.    458: 3F3C 0002      '?<..'           PUSH    #2
  3555.    45C: 3F2E FBF2      200FBF2          PUSH    vem_2(A6)
  3556.    460: 2F0C           '/.'             PUSH.L  A4
  3557.    462: 4EBA FF0C      2000370          JSR     proc106
  3558.    466: 101F           '..'             POP.B   D0
  3559.    468: 0A00 0001      '....'           EORI.B  #1,D0
  3560.    46C: 6700 0086      20004F4          BEQ     lem_2
  3561.    470: 4267           'Bg'             CLR     -(A7)
  3562.    472: 3F3C 0001      '?<..'           PUSH    #1
  3563.    476: 3F2E FBF2      200FBF2          PUSH    vem_2(A6)
  3564.    47A: 2F0C           '/.'             PUSH.L  A4
  3565.    47C: 4EBA FEF2      2000370          JSR     proc106
  3566.    480: 101F           '..'             POP.B   D0
  3567.    482: 0A00 0001      '....'           EORI.B  #1,D0
  3568.    486: 676C           20004F4          BEQ.S   lem_2
  3569.    488: 42A7           'B.'             CLR.L   -(A7)
  3570.    48A: 3F3C 0101      '?<..'           PUSH    #257
  3571.    48E: 42A7           'B.'             CLR.L   -(A7)
  3572.    490: 70FF           'p.'             MOVEQ   #-1,D0
  3573.    492: 2F00           '/.'             PUSH.L  D0
  3574.    494: A9BD           '..'             _GetNewWindow ; (windowID:INTEGER; wStorage:Ptr;
  3575. behind:WindowPtr):WindowPtr 
  3576.    496: 265F           '&_'             POP.L   A3
  3577.    498: 2F0B           '/.'             PUSH.L  A3
  3578.    49A: A873           '.s'             _SetPort ; (port:GrafPtr) 
  3579.    49C: 3F3C 0010      '?<..'           PUSH    #16
  3580.    4A0: 3F3C 001C      '?<..'           PUSH    #28
  3581.    4A4: A893           '..'             _MoveTo ; (h,v:INTEGER) 
  3582.    4A6: 4267           'Bg'             CLR     -(A7)
  3583.    4A8: A887           '..'             _TextFont ; (font:FontCode) 
  3584.    4AA: 42A7           'B.'             CLR.L   -(A7)
  3585.    4AC: 3F3C 0100      '?<..'           PUSH    #256
  3586.    4B0: A9BA           '..'             _GetString ; (stringID:INTEGER):StringHandle 
  3587.    4B2: 2C1F           ',.'             POP.L   D6
  3588.    4B4: 2046           ' F'             MOVEA.L D6,A0
  3589.    4B6: 2F10           '/.'             PUSH.L  (A0)
  3590.    4B8: A884           '..'             _DrawString ; (s:Str255) 
  3591.    4BA: 4267           'Bg'             CLR     -(A7)
  3592.    4BC: 42A7           'B.'             CLR.L   -(A7)
  3593.    4BE: 3F3C 0001      '?<..'           PUSH    #1
  3594.    4C2: 4EAD 002A      1000186          JSR     Eject(A5)
  3595.    4C6: 3E1F           '>.'             POP     D7
  3596.    4C8: 486E FBF4      200FBF4 lem_1    PEA     vem_3(A6)
  3597.    4CC: 4EBA FEEE      20003BC          JSR     proc107
  3598.    4D0: 4267           'Bg'             CLR     -(A7)
  3599.    4D2: 3F2E FBF4      200FBF4          PUSH    vem_3(A6)
  3600.    4D6: 2F0C           '/.'             PUSH.L  A4
  3601.    4D8: 4EBA FE48      2000322          JSR     proc105
  3602.    4DC: 1A1F           '..'             POP.B   D5
  3603.    4DE: 4267           'Bg'             CLR     -(A7)
  3604.    4E0: 42A7           'B.'             CLR.L   -(A7)
  3605.    4E2: 3F2E FBF4      200FBF4          PUSH    vem_3(A6)
  3606.    4E6: 4EAD 002A      1000186          JSR     Eject(A5)
  3607.    4EA: 3E1F           '>.'             POP     D7
  3608.    4EC: 1005           '..'             MOVE.B  D5,D0
  3609.    4EE: 67D8           20004C8          BEQ     lem_1
  3610.    4F0: 2F0B           '/.'             PUSH.L  A3
  3611.    4F2: A914           '..'             _DisposWindow ; (theWindow:WindowPtr) 
  3612.    4F4: 4CDF 18F0      'L...'  lem_2    MOVEM.L (A7)+,D4-D7/A3-A4
  3613.    4F8: 4E5E           'N^'             UNLK    A6
  3614.    4FA: 4E75           'Nu'             RTS     
  3615.  
  3616.  
  3617.    4FC: '............'         data76   DC.W    $8100,8,0,$4FC,$FC00,0
  3618. The first thing to do here is to quickly scan for trap names.  There are quite a few, but one should
  3619. stick out.  Remember that we are looking for some reference to STR #256.  Note the GetString trap. 
  3620. Immediately before the trap is a PUSH #256...that's our guy!  So, at this point, we know where the
  3621. string is being loaded and drawn.  Since this procedure is called from the Main procedure, we can bet
  3622. that the key-disk check is also in this proc.  Note that this is not always the case - often when you
  3623. find the procedure that loads the dialog or string, you need to back trace to find out where the
  3624. actual error generator is located.  That is where the Refs line (right below the VEND) in the listing
  3625. comes in handy.  Note that this proc is called by not only Sorcerer, but also by proc37.  This might
  3626. mean that the program checks the key-disk later in its execution.  But if you load up proc37, you
  3627. would find that it simply Unloads the segment so it is harmless.
  3628. At this point, all we need to do is disable the disk-check.  So, start scanning down the listing and
  3629. ask yourself "Where is a branch that will skip over the GetString trap?".  If you find that branch
  3630. and make it always branch then odds are the program is cracked.  Nosy will help out here.  We are
  3631. looking for a spot in the listing that a branch can jump to that will skip over the error.  We have
  3632. two choices in this listing: lem_1 and lem_2.  Check out lem_1, and you will see a couple of problems
  3633. with it.  First of all, see what piece of code branches to it.  There is a JSR  Eject, then a test,
  3634. and a BEQ lem_1.  Also note that there is a DisposeWindow after it.  We might guess that
  3635. DisposeWindow is disposing the error dialog.  We might also guess that lem_1 is being used as a loop
  3636. to eject bad disks and request key-disks.  Well, let's give lem_2 a shot.  Now this one looks good -
  3637. it is located right down at the procedures exit, so, if something is branching here, all the above
  3638. stuff gets skipped.
  3639. So, just select lem_2 and hit cmd-f to let Nosy find all the references to lem_2 in the listing. 
  3640. Line 452 is the key.  Note, D0 gets a result from an unknow procedure, then is EORd with 1, and then
  3641. the branch occurs.  It sure looks like changing that branch from BEQ to BRA would gurrantee that the
  3642. error never occured.  Let's try it.  From the assembly instruction listing, we see that BEQ is 67,
  3643. and BRA is 60.  So, look at the first line in the above listing and we see that it is segment 2.  So,
  3644. open CODE resource 2 in Resedit, and skip down to address 456 (remember, take the Nosy address and
  3645. add 4 to find the Resedit address).  
  3646. 
  3647. There it is, on line 450.  See the 6700?  That sure matches what we find in Nosy, so that is our guy. 
  3648. Change the 67 to 60 by clicking to the right of the 67, hitting backspace or delete, and typing 60. 
  3649. That's it!  Now quit Resedit and save changes.  Launch the program and the protection is gone!
  3650. Let me quickly mention one last thing.  The above crack involved looking for a branch that would skip
  3651. over the problem area, and making damn sure that that branch always executed.  But suppose that the
  3652. program was setup so that after the disk check, the program branched to the error section.  In this
  3653. case, we would want to make sure the branch never executed.  There are two ways to do this.  First
  3654. off, you can change the branch to its logical opposite - BCC to BCS, BNE to BEQ, etc.  That way, the
  3655. condition that triggers the error will now trigger the opposite, and run properly.  The second method
  3656. is to simply replace the trap with a NOP.  That way, the branch never executes no matter what
  3657. happens.
  3658. Look for upcoming material on more specific cracking methods and more actual cracks.
  3659. later - The Shepherd
  3660. Beta Notes: 10/17/91
  3661.  
  3662. The following bold entries constitute a tentative outline for topics to dicuss in detail.  Some of
  3663. these topics will require a fair amount of research on my part - in particular, the Eve and
  3664. Encryption sections will take some time.  After this section come the live cracks.  These represent
  3665. an attempt to take a novice cracker through every step of the cracking process detailing choices and
  3666. decisions that I would make as I go and why I would make them.
  3667.  
  3668. Any feedback would be greatly appreciated - especially from any novice crackers who find parts of
  3669. this document incomprehensible.  Note that this is a rough draft - there are bound to be errors
  3670. although hopefully no logical ones (just syntactical and/or spelling).
  3671.  
  3672. Determining where to start looking
  3673.  
  3674. 1) Types of protection
  3675.     a) Serial number schemes
  3676.     b) Registration codes
  3677.     c) Network serial checks [AppleTalk driver stuff]
  3678.     d) Hardware plugs - see below
  3679.     e) Encryption - see below
  3680.     f) Time stamps
  3681.     g) Key disk
  3682.  
  3683. How to break into programs
  3684.  
  3685. 1) Trap interrupts
  3686.     a) Dialog/Alert traps
  3687.     b) MenuSelect
  3688.     c) InitFonts etc.
  3689. 2) Manual entrance of TMON [Good luck]
  3690. 3) Automatic TMON entrance via code modification [_Debugger trap insertion]
  3691.     a) Determining an address with Nosy
  3692.     b) Determining an address from the Jump Table
  3693.     c) 
  3694.  
  3695. Using TMON, Nosy, and ResEdit together
  3696.  
  3697. 1) Determining address offsets
  3698. 2) Nosy vs TMON
  3699.     a) Why Nosy "feels better"
  3700.     b) Why TMON is virtually omniscient
  3701.  
  3702. TMON Tricks
  3703.  
  3704. 1) TMON tricks with register values, flags, and instruction modification
  3705. 2) One step ModalDialog hassles [Serial number schemes]
  3706. 3) TMON Pro shortcuts
  3707.  
  3708. Determining the type of crack to apply
  3709.  
  3710. 1) Bypasses vs cracks
  3711. 2) Finding the key code
  3712. 3) Branch switching
  3713.     a) Mention something about branch op-codes - 2 and 4 byte instructions and offsets
  3714. 4) Flag/variable modification
  3715. 5) Code modification
  3716.  
  3717. Everything you always wanted to know about the CODE 0 Jump Table.
  3718.  
  3719. 1) What it is and how it works
  3720. 2) Locating an entry point
  3721. 3) Modifications
  3722.  
  3723. Hardware plugs
  3724.  
  3725. 1) General tips [Device Manager stuff]
  3726. 2) Eve bullshit
  3727.  
  3728. Encrypted Code
  3729.  
  3730. Unless you are one hell of a genius at cryptology and have lots of time to kill, the encrypted CODE
  3731. resources will have to be de-crypted and written back to the program.  Here is why:  to decrypt
  3732. itself, a program will usually either take a known seed number and use it on each encrypted byte of
  3733. the code or else it will start with some byte in the code and do a forward decrypt,  i.e. the first
  3734. byte decrypts the second byte, the new second byte decrypts the third byte, and so on.  A simple
  3735. method might be to have some code that looks like this:
  3736.  
  3737.     MOVE    #1000,D0
  3738.     LEA    encryptedshit,A0
  3739.     LEA    encryptedshit-1,A1
  3740. loop1    EOR.L    (A1)+,(A0)+
  3741.     DBRA    D0,loop1
  3742. encryptedshit    Here is where the encrypted gibberish begins.
  3743.  
  3744. This is a simple example, but note how it functions.  D0 gets the number of longwords to decrypt, A0
  3745. is the destination (where the decrypted stuff will go - which is right back over the encrypted stuff)
  3746. and A1 gets the decrypting key which is the long word that was previously decrypted.  Then the code
  3747. simply loops D0 times writing over the encrypted code with the decrypted code.  After this code has
  3748. finished, the program continues execution right where the encrypted (and now decrypted) code begins. 
  3749. Now cosider: somewhere in the encrypted stuff is the error check that you have to modify.  This will
  3750. be simple enough to locate assuming that you can run the decryption routine and then immediately
  3751. regain control in TMON.  The problem is that when you go to modify the error check so that it always
  3752. passes, the modification screws up the decryption routine.  This is because the decryption routine
  3753. requires the exact original values to run properly since these values are the keys that the code
  3754. uses.  So a crack using traditional methods requires that you not only change the error branch, but
  3755. that you also change every other encrypted value such that the decryption routine still runs properly
  3756. - no small feat!
  3757.  
  3758. A much more feasable method would be to decrypt the code, make the necessary modifications to the
  3759. error routine, and then disable the decryption routine (just branching around it would do) and
  3760. writing the whole mess (un-encrypted) back to the original code resource.
  3761.  
  3762. So much for the theory, now if I could just crack one of these suckers...
  3763.  
  3764.  
  3765. Live Cracks
  3766.  
  3767.  
  3768. MultiClip 2.0
  3769.  
  3770. This program uses a network checking algorithm to determine whether multiple copies with the same
  3771. serial number are currently running - if you don't use this program on a network, you will never see
  3772. the error.
  3773.  
  3774. Step 1:  Where to start looking.
  3775.  
  3776. There are actually several good places to begin looking for the protection (especially if you have
  3777. already cracked it - but I will assume that you have not).  First of all, since the program scans the
  3778. network, it is probably using the _Open Trap somewhere early in its code to to access the Appletalk
  3779. driver.  Second, it displays an error dialog (or alert) so we could open it up in Resedit, find the
  3780. error dialog (and note its ID # for later use) and then Nosy it and look at procedures that call
  3781. ModalDialog or one of the Alert traps to try and find the one that displays the dialog with the
  3782. proper ID #.  Third, we could have TMON trap either 1) ModalDialog if it is a dialog or 2) StopAlert,
  3783. CautionAlert or NoteAlert if it is an Alert and begin tracing from that point backwords.  Fourth, we
  3784. could just Nosy it and start from the top (the slow way).
  3785.  
  3786. Whenever a program displays an error dialog (not a serial number dialog which seems to be in vogue
  3787. these days) I almost always find the ID # of the dialog or alert and begin looking at procs in Nosy,
  3788. so let's start there.  In Resedit, we note that it is Dialog (and not Alert) #128 that is the
  3789. problem.  On to Nosy.  After Nosy analyzes the INIT resource, open up the Trap Refs List under the
  3790. Display menu and scroll down to GetNewDialog.  Here you will find two listings: ASKNAME and
  3791. PUTREGISTERDLOG.  Since there are only two we can quickly check them both out (if there were a bunch,
  3792. I would probably try a different method).  First let us look at ASKNAME -  here is the listing down
  3793. to the GetNewDialog:
  3794.  
  3795.    42BA:                                 QUAL    ASKNAME ; b# =184  s#1  =proc54
  3796.  
  3797.                                  vdu_1     VEQU  -26
  3798.                                  vdu_2     VEQU  -18
  3799.                                  vdu_3     VEQU  -12
  3800.                                  vdu_4     VEQU  -10
  3801.                                  vdu_5     VEQU  -8
  3802.                                  param1    VEQU  8
  3803.                                  funRslt   VEQU  12
  3804.     42BA:                                 VEND    
  3805.  
  3806.                                ;-refs - com_43    MYFILTERFORNAME  
  3807.  
  3808.     42BA: 4E56 FFE6      'NV..'  ASKNAME  LINK    A6,#-$1A
  3809.     42BE: 48E7 0318      'H...'           MOVEM.L D6-D7/A3-A4,-(A7)
  3810.     42C2: 2C2E 0008      2000008          MOVE.L  param1(A6),D6
  3811.     42C6: 42A7           'B.'             CLR.L   -(A7)
  3812.     42C8: 4EBA E642      100290C          JSR     proc19
  3813.     42CC: 285F           '(_'             POP.L   A4
  3814.     42CE: 486E FFF8      200FFF8          PEA     vdu_5(A6)
  3815.     42D2: A874           '.t'             _GetPort ; (VAR port:GrafPtr) 
  3816.     42D4: 42A7           'B.'             CLR.L   -(A7)
  3817.     42D6: 302C 001E      '0,..'           MOVE    30(A4),D0
  3818.     42DA: D07C 0014      '.|..'           ADD     #20,D0
  3819.     42DE: 3F00           '?.'             PUSH    D0
  3820.     42E0: 42A7           'B.'             CLR.L   -(A7)
  3821.     42E2: 70FF           'p.'             MOVEQ   #-1,D0
  3822.     42E4: 2F00           '/.'             PUSH.L  D0
  3823.     42E6: A97C           '.|'             _GetNewDialog ; (DlgID:INTEGER; wStorage:Ptr;
  3824. behind:WindowPtr):DialogPtr 
  3825.  
  3826. The first thing to do is to locate the _GetNewDialog and determine its associated parameters:
  3827. actually all we care about is the first parameter, the ID #.  Tracing backwords, we see that -1 is
  3828. the third parm, 0 is the second parm, and 30(A4) + #20 (from the ADD #20,D0) is the first parm. 
  3829. Well, we have a problem here.  Instead of a nice plain ID # being passed to GetNewDialog, the ID # is
  3830. hidden on the stack frame somewhere.  At this point it is best to mark this proc as indeterminite and
  3831. go on to the next one.  If we must come back to this one then we will have to figure out if ID #128
  3832. is valid for this proc and go from there.  So let us look at PUTREGISTERDLOG
  3833.  
  3834.   33AC:                                 QUAL    PUTREGISTERDLOG ; b# =141  s#1  =proc35
  3835.  
  3836.                                vdb_1     VEQU  -286
  3837.                                vdb_2     VEQU  -278
  3838.                                vdb_3     VEQU  -276
  3839.                                vdb_4     VEQU  -274
  3840.                                vdb_5     VEQU  -272
  3841.                                vdb_6     VEQU  -270
  3842.                                vdb_7     VEQU  -268
  3843.                                vdb_8     VEQU  -264
  3844.                                vdb_9     VEQU  -262
  3845.                                vdb_10    VEQU  -256
  3846.                                param1    VEQU  8
  3847.   33AC:                                 VEND    
  3848.  
  3849.                                ;-refs - INIT1     
  3850.  
  3851.                                PUTREGISTERDLOG
  3852.   33AC: 4E56 FEE2      'NV..'           LINK    A6,#-$11E
  3853.   33B0: 2F0C           '/.'             PUSH.L  A4
  3854.   33B2: 206E 0008      2000008          MOVEA.L param1(A6),A0
  3855.   33B6: 43EE FF00      200FF00          LEA     vdb_10(A6),A1
  3856.   33BA: 703F           'p?'             MOVEQ   #63,D0
  3857.   33BC: 22D8           '".'    ldb_1    MOVE.L  (A0)+,(A1)+
  3858.   33BE: 51C8 FFFC      10033BC          DBRA    D0,ldb_1
  3859.   33C2: 42A7           'B.'             CLR.L   -(A7)
  3860.   33C4: 3F3C 0080      '?<..'           PUSH    #128
  3861.   33C8: 42A7           'B.'             CLR.L   -(A7)
  3862.   33CA: 70FF           'p.'             MOVEQ   #-1,D0
  3863.   33CC: 2F00           '/.'             PUSH.L  D0
  3864.   33CE: A97C           '.|'             _GetNewDialog ; (DlgID:INTEGER; wStorage:Ptr;
  3865. behind:WindowPtr):DialogPtr 
  3866.  
  3867.  
  3868. Once again, find the GetNewDialog and determine the parms.  Here we have -1 for the third, 0 for the
  3869. second, and lo and behold, 128 for the first.  This is definately our procedure.  Note that this is
  3870. an extremely easy example as no attempt has been made to disguise the ID # - it is clearly 128, the
  3871. value we have been looking for all along.
  3872.  
  3873. Determining how to implement the crack.
  3874.  
  3875.  The obvious place to start looking is just before the error dialog has been loaded.  Here is that
  3876. section of code from the above procedure:
  3877.  
  3878. LINK    A6,#-$11E
  3879. PUSH.L  A4
  3880. MOVEA.L param1(A6),A0
  3881. LEA     vdb_10(A6),A1
  3882. MOVEQ   #63,D0
  3883. ldb 1    MOVE.L  (A0)+,(A1)+
  3884. DBRA    D0,ldb_1        Next comes the code we just looked at
  3885. CLR.L   -(A7)
  3886. PUSH    #128
  3887. CLR.L   -(A7)
  3888. MOVEQ   #-1,D0
  3889. PUSH.L  D0
  3890. _GetNewDialog
  3891.  
  3892. As we look at this code, keep in mind what it is that we are looking for.  We know that the program
  3893. is capable of loading without this error, so somewhere it has to be checking the network and then
  3894. either branching to the error code (if it detects a copy of itself) or else branching around the
  3895. error code.  So we need to find the branch that is causing this segment of code to execute.  A quick
  3896. scan of the code that precedes the error dialog code should reveal nothing of interest.  A Link
  3897. followed by a 63 word Move Loop - no branches of any consequence whatsoever.  If you are wondering
  3898. why we can immediately eliminate the DBRA  D0,ldb1 (after all, it is a branch) then ask yourself
  3899. this:  1st, where does the branch go? Answer: to the line above the branch instruction.  2nd, what
  3900. (if any) conditions is it checking? Answer: it checks to see if D0 (an obvious loop counter in this
  3901. case) is equal to zero.  If the branch does not either 1) branch directly to the error code (in this
  3902. case it would have to be branching to the CLR.L -(A7) ) or 2) branch around the error code (somewhere
  3903. after the GetNewDialog and the ensuing ModalDialog and probably even an ensuing DisposeDialog) then
  3904. the branch is almost certainly a bad candidate.  You particulaly should be able to immediately
  3905. eliminate loop terminator branches like the one above.
  3906.  
  3907. Well, since we have eliminated the only branch in this procedure above the GetNewDialog, we will have
  3908. to look elsewhere.  The next obvious place to look is in the procedure that called this one.  Again
  3909. Nosy makes this a snap.  Take a look at the line right above the code listing that read refs - INIT1. 
  3910. The refs line tells you every procedure that calls the one you are currently looking at.  Luckily,
  3911. there is only one, so let us look at it next.  Since this is a long procedure, I am only listing the
  3912. section that surrounds the JSR PUTREGISTERDLOG line.  I should also mention that I am writing this
  3913. with a copy that I cracked a while ago and in un-cracking it for this document, could not remember
  3914. exactly what the changed code was.  I will show you where your code listing might differ from mine
  3915. below:
  3916.  
  3917.    196: 4268 0004      'Bh..'           CLR     4(A0)
  3918.    19A: 4228 0006      'B(..'           CLR.B   6(A0)
  3919.    19E: 4228 0007      'B(..'           CLR.B   7(A0)
  3920.    1A2: 43FA 036E      1000512          LEA     data2,A1    ; len= 1
  3921.    1A6: 45E8 0009      'E...'           LEA     9(A0),A2
  3922.    1AA: 4EBA 0392      100053E          JSR     proc2
  3923.    1AE: 43FA 03A2      1000552          LEA     data4,A1    ; 'Multi'
  3924.    1B2: 4EBA 038A      100053E          JSR     proc2
  3925.    1B6: 43FA 03AC      1000564          LEA     data7,A1    ; len= 2
  3926.    1BA: 4EBA 0382      100053E          JSR     proc2
  3927.    1BE: 4A6E FFEC      200FFEC          TST     vab_2(A6)
  3928.    1C2: 6756           100021A          BEQ.S   lab_13
  3929.    1C4: 4FEF FFFE      'O...'           LEA     -2(A7),A7
  3930.    1C8: 2F2E FFEE      200FFEE          PUSH.L  vab_3(A6)
  3931.    1CC: 4EBA 2C88      1002E56          JSR     proc29
  3932.    1D0: 301F           '0.'             POP     D0
  3933.    1D2: 6646           100021A          BNE.S   lab_13
  3934.    1D4: 4FEF FFCE      'O...'           LEA     -50(A7),A7
  3935.    1D8: 204F           ' O'             MOVEA.L A7,A0
  3936.    1DA: 317C FFF6 0018 '1|....'         MOVE    #$FFF6,ioCRefNum(A0)
  3937.    1E0: 216E FFEE 001E 200FFEE          MOVE.L  vab_3(A6),ioSEBlkPtr(A0)
  3938.    1E6: 317C 00FC 001A '1|....'         MOVE    #252,CSCode(A0)
  3939.    1EC: A004           '..'             _Control ; (A0|IOPB:ParamBlockRec):D0\OSErr 
  3940.    1EE: 4FEF 0032      'O..2'           LEA     50(A7),A7
  3941.    1F2: 206E FFEE      200FFEE          MOVEA.L vab_3(A6),A0
  3942.    1F6: A01F           '..'             _DisposPtr ; (A0/p:Ptr) 
  3943.    1F8: 486D FFFC           -4          PEA     glob1(A5)
  3944.    1FC: A86E           '.n'             _InitGraf ; (globalPtr:Ptr) 
  3945.    1FE: A8FE           '..'             _InitFonts  
  3946.    200: A912           '..'             _InitWindows  
  3947.    202: A9CC           '..'             _TeInit  
  3948.    204: 42A7           'B.'             CLR.L   -(A7)
  3949.    206: A97B           '.{'             _InitDialogs ; (resumeProc:ProcPtr) 
  3950.    208: A850           '.P'             _InitCursor  
  3951.    20A: 42B8 0A6C         $A6C          CLR.L   DeskHook
  3952.    20E: 487A 0302      1000512          PEA     data2       ; len= 1
  3953.    212: 4EBA 3198      10033AC          JSR     PUTREGISTERDLOG
  3954.    216: 4EFA 0316      100052E          JMP     com_2
  3955.    21A: 4227           'B''    lab_13   CLR.B   -(A7)
  3956.    21C: A99B           '..'             _SetResLoad ; (AutoLoad:BOOLEAN) 
  3957.    21E: 42A7           'B.'             CLR.L   -(A7)
  3958.    220: 2F3C 4452 5652 '/<DRVR'         PUSH.L  #'DRVR'
  3959.    226: 487A 2156      100237E          PEA     data35      ; len= 12
  3960.    22A: A9A1           '..'             _GetNamedResource ; (theType:ResType; name:Str255):Handle 
  3961.    22C: 1F3C 0001      '.<..'           PUSH.B  #1
  3962.    230: A99B           '..'             _SetResLoad ; (AutoLoad:BOOLEAN) 
  3963.   
  3964. First off, we need to find the line that calls the error procedure we just finished looking at.  In
  3965. this case the line will be either JSR PUTREGISTERDLOG or BSR PURREGISTERDLOG.  We find the correct
  3966. line just above lab 13.  Now, quickly note the structure we are dealing with: we have JSR
  3967. PUTREGISTERDLOG (which does all the error dialog stuff) followed by a JMP instruction.  So the
  3968. program is leaving the main flow of control after doing the error dialog.  This is important because
  3969. we can see that logically, there should be a branch that skips this piece of code and continues on
  3970. with lab 13.  If we scan backwords from the JSR PUT... we see a bunch of Initialization traps
  3971. preceded by some Moves - but then notice this code:
  3972.  
  3973. JSR     proc2
  3974. TST     vab_2(A6)
  3975. BEQ.S   lab_13
  3976. LEA     -2(A7),A7
  3977. PUSH.L  vab_3(A6)
  3978. JSR     proc29
  3979. POP     D0
  3980. BNE.S   lab_13
  3981.  
  3982. Here is where I forget what the original code looked like so your listing might say BEQ.S lab 13 (for
  3983. the second branch that is).  Anyways, this code looks really good since it branches around the error
  3984. section.  At this point, we might hazard a guess and simply make these Branch instructions always
  3985. execute by changing them to BRA lab 13.  This might be an incorrect crack since the program could be
  3986. making other checks above this code - we can eliminate this chance by continuing scanning upwards
  3987. looking for references to lab 13 until the beginning of this procedure.  What I would do in a case
  3988. like this is make a real fast check of about 50 or so lines of code above this looking for branches
  3989. refering to lab 13.  If I find one, modify it...if not, then make the crack and test it.  If the
  3990. crack fails, then I would know to keep looking.
  3991.  
  3992. A quick note:  The flow of the program seems to suggest that merely changing the first branch from
  3993. BEQ to BRA would suffice since this instruction always executes (it is not branched around anywhere)
  3994. and once this instruction branches to lab 13 there would be no need to change the second branch. 
  3995. However, I am writing this having already cracked this program and the method I used was to change
  3996. the second branch only.  Since I know that this works and cannot test any other method (not having a
  3997. network at my disposal), I will proceed in this manner.  The would-be cracker could certainly try
  3998. changing the first branch and it looks to me as if this would work.
  3999.  
  4000. So how is the crack applied?  Well, in this case, it looks like the program branches to lab 13 only
  4001. if the serial check is OK (i.e. there are no extra copies running on the network) so we need to to
  4002. make this branch always execute.  The easiest way to do this is to change the BNE.S lab 13 to BRA.S
  4003. lab 13 - branch not equal turns into branch always.  So, simply pop over to Resedit and open the
  4004. proper resource (INIT in this case).  To determine the ID of the resource, look at the top of the
  4005. procedure window in Nosy.  The first line will contain an s# followed by a number.  This is the
  4006. segment number or ID # of the resource (in this case it is obvious since there is only one INIT
  4007. resource, but for CODE resources this is really handy).  Once the resource is open (make sure you do
  4008. not have the Resedit disassembler running - if you do, select Open Using Hex Editor from the Resource
  4009. menu) scan down to the line that most closely matches the line you want to modify - in this case our
  4010. line is 1D2 so find line 1D0 in Resedit and look over 2 bytes.  There should be the code 6646.  Just
  4011. click in front of the 66, backspace to delete it,  and type 60 (You can find these op-code numbers in
  4012. the Cracker's Guide Part 1).  Now quit and save changes and the crack is complete.
  4013.  
  4014. Infini-d 1.1
  4015.  
  4016. This program uses the common serial number / personalize dialog scheme.
  4017.  
  4018. Step 1:  Where to start looking.
  4019.  
  4020. We have two good options here: 1) Find the Dialog ID # in Resedit and use Nosy's Trap Refs List or 2)
  4021. trap ModalDialog in TMON and start tracing from there.  I tend to use the second method, usually
  4022. because I can implement the crack on the fly in TMON and actually run the program.  Then I go back
  4023. later and figure out how do a full crack with Nosy.  Note that withe the second method we do not have
  4024. to go through every stupid dialog in the program.  Rather we can simply find the unfriendly
  4025. ModalDialog and let TMON tell us which code resource we are in.
  4026.  
  4027. First, drop into TMON and set a trap intercept for _ModalDialog then exit TMON and launch Infini-D. 
  4028. TMON will proceed to stop execution at the first ModalDialog trap.  Since it is possible for a
  4029. program to have ModalDialog traps before the one that actually does the serial number stuff my first
  4030. step is to immediately exit TMON and keep track of how many ModalDialogs occur before the serial
  4031. number dialog comes up.  In this case it is the first ModalDialog, so I would have to then quit and
  4032. start over, this time not exiting TMON when the trap occurs.
  4033.  
  4034. Once you are in TMON, open an Assembly window to (PC) to look at the code that is executing.  I
  4035. forget exactly, but essentially what you would see is the ModalDialog trap followed by a couple of
  4036. meaningless instructions and an RTS.  Since nothing happens after the ModalDialog, we would need to
  4037. Step through the RTS to get back to the procedure that called this one.
  4038.  
  4039. I should make a quick note here:  this technique of making an on the fly crack via TMON usually means
  4040. that you are going to ruin the application, i.e. you are going to end up with a serialized program
  4041. that no longer needs to be cracked.  This is not a true crack, rather this is a bypass - once this is
  4042. done, the program is personalized and ready to run; in a sense you are letting the program crack
  4043. itself.  If you wanted to make a true cracked copy, you would have to look at exactly which branches
  4044. were modified in TMON and then go into Resedit and change the same instructions (with an
  4045. un-serialized copy of the application).
  4046.  
  4047. OK, enough about that.  Here is the code you would see:
  4048.  
  4049. PEA      $157A(A5)
  4050. MOVE.L  $000C(A6),-(A7)
  4051. _ModalDialog
  4052. UNLK      A6
  4053. RTS
  4054.  
  4055. Since the procedure ends right after the ModalDialog call, we need to step through the RTS to see
  4056. what called this procedure...and here is that code:
  4057.  
  4058. 001E50B4: LINK.W    A6,#$FFFE
  4059. 001E50B8: PEA      `FFFE(A6)
  4060. 001E50BC: CLR.L      -(A7)
  4061. 001E50BE: JSR      $1572(A5)
  4062. 001E50C2: ADDQ.L    #8,A7
  4063. 001E50C4: CMPI.W    #$0001,`FFFE(A6)
  4064. 001E50CA: BEQ.S      ^$001E50D8        
  4065. 001E50CC: CMPI.W      #$0002,`FFFE(A6)
  4066. 001E50D2: BEQ.S      ^$001E50D8        
  4067. 001E50D4: MOVEQ      #$00,D0
  4068. 001E50D6: BRA.S      ^$001E50DA        
  4069. 001E50D8: MOVEQ      #$01,D0
  4070. 001E50DA: TST.W      D0
  4071. 001E50DC: BEQ.S      ^$001E50B8        
  4072. 001E50DE: CMPI.W    #$0001,`FFFE(A6)
  4073. 001E50E4: BNE.S      ^$001E50EA        
  4074. 001E50E6: MOVEQ      #$01,D0
  4075. 001E50E8: BRA.S      ^$001E50EC        
  4076. 001E50EA: MOVEQ      #$00,D0
  4077. 001E50EC: UNLK      A6
  4078. 001E50EE: RTS
  4079.  
  4080. Well, there is quite a bit of comparing and branching going on here so we had better see if we can
  4081. figure out what is happening.  After the Link, the dialog handle is pushed on the stack, space for a
  4082. return value (or maybe a parameter with value 0) is put on the stack and then the ModalDialog
  4083. procedure is called.  This is pretty standard.  Next, the stack is restored to its original value and
  4084. something is compared to 1, branch if so, then compare the same thing to 2 and branch if so.  Notice
  4085. an important thing here, namely that this procedure never calls GetDItem or GetIText nor does it call
  4086. any more subroutines so this procedure cannot be the one that checks the serial number.  So it is
  4087. probably a safe bet that this procedure is testing to see what exactly the user did - hit OK? hit
  4088. Cancel? Type in a keystroke?  Assuming for the moment that this is the case, take a wild guess what
  4089. the various dialog item numbers are?  You guessed it...1 is the OK button, 2 is the Cancel button. 
  4090. Now look at the code and you can quickly see what is happening (still assuming our item number theory
  4091. is correct).  First, if the item number hit was one (OK button) then branch down, and put a 1 in D0. 
  4092. If the item number hit was 2 (Cancel button) then do the same thing.  Otherwise put a zero in D0. 
  4093. Finally, TST D0 and if it was 0 (neither button hit) then loop back and call ModalDialog again.  At
  4094. this point the program knows one of the buttons was hit.  So, if it was not the OK button, branch
  4095. down and put 0 in D0 otherwise put a 1 in D0 (so that's Cancel = 0, OK = 1).  When we look at the
  4096. procedure that called this one, we know that D0 will tell that procedure what happened (either OK or
  4097. Cancel).
  4098.  
  4099. Note that this is one of those problem ModalDialog calls that exits everytime you hit a keystroke so
  4100. you cannot just type in your name and serial number, hit OK to get back to TMON, and crack the
  4101. sucker.  Rather you have to either 1) settle for only typing in one letter before you crack it or 2)
  4102. set a breakpoint just past the part were it tests for the OK button being hit, clear the ModalDialog
  4103. trace, and exit - TMON won't interrupt until you hit the OK button and the breakpoint is encountered.
  4104.  
  4105. Finally, here is the last piece of code - the procedure that called the above procedure:
  4106.  
  4107. 001E4FBE: ADDQ.L  #6,A7
  4108. 001E4FC0:JSR    ^$001E50B4    
  4109. 001E4FC4: MOVE.W  D0,`FFFE(A6)        Here is where we returned from the above procedure. 1 = OK, 0 =
  4110. Cancel
  4111. 001E4FC8: CMPI.W  #$0001,`FFFE(A6)
  4112. 001E4FCE:BNE.S    ^$001E5012        Branch if Cancel hit
  4113. 001E4FD0:PEA    `FEF8(A6)
  4114. 001E4FD4: MOVE.W  #$000A,-(A7)
  4115. 001E4FD8:JSR    ^$001E4F58    
  4116. 001E4FDC: ADDQ.L  #6,A7        
  4117. 001E4FDE:PEA    `FEF8(A6)
  4118. 001E4FE2:JSR    ^$001E52AC    
  4119. 001E4FE6: ADDQ.L  #4,A7
  4120. 001E4FE8: MOVE.W  D0,`FFFC(A6)
  4121. 001E4FEC:TST.W    `FFFC(A6)
  4122. 001E4FF0:BNE.S    ^$001E5012    
  4123. 001E4FF2: MOVE.W  #$0001,-(A7)
  4124. 001E4FF6:CLR.W    -(A7)
  4125. 001E4FF8: MOVE.W      #$0034,-(A7)
  4126. 001E4FFC:JSR    $107A(A5)
  4127. 001E5000: ADDQ.L  #6,A7
  4128. 001E5002: MOVE.L  582(A5),-(A7)
  4129. 001E5006: MOVE.W  #$000A,-(A7)
  4130. 001E500A:CLR.W    -(A7)
  4131. 001E500C: MOVE.W  #$7FFF,-(A7)
  4132. 001E5010: SelIText
  4133. 001E5012: CMPI.W  #$0001,`FFFE(A6)    True if OK was hit
  4134. 001E5018:BNE.S    ^$001E5020    
  4135. 001E501A:TST.W    `FFFC(A6)        Unknown: returned value from JSR above
  4136. 001E501E: BEQ.S    ^$001E4FC0
  4137. 001E5020: CMPI.W  #$0001,`FFFE(A6)
  4138. 001E5026:BNE.S    ^$001E5070    
  4139. 001E5028:PEA    `FF38(A6)
  4140. 001E502C: MOVE.W  #$0006,-(A7)
  4141. 001E5030:JSR    ^$001E4F58    
  4142. 001E5034: ADDQ.L  #6,A7
  4143.  
  4144. Well, there is a lot of crap here and if you decided to trace the two JSRs you would be in for a long
  4145. ride.  The first thing to try is to deduce what will happen based on what we already know - we know
  4146. that if the wrong serial number is entered, the program will go back to ModalDialog to let you change
  4147. it.  So we need to find a branch that goes back above line 1E4FC0 (the ModalDialog JSR).  If we can
  4148. find that branch and avoid it, we should be safe.  So we will start tracing down from where the
  4149. program returned, not making any assumptions yet, but looking at where the branches go.  Right away
  4150. you will note two JSRs.  Take a look at the parameters passed, and you will note the pair of PEA
  4151. FEF8(A6) instructions.  So this same piece of information is being passed to both subroutines -
  4152. nothing to write home about, but interesting.  The real key you should notice here is that there is a
  4153. TST and BNE after the second subroutine.  This is the first chance the program has to make any
  4154. decisions (although what decisions we don't know).  Let's assume this branch does not execute (you
  4155. could assume either way and wind up with the answer) i.e. FFFC(A6) = 0 - some stuff happens that we
  4156. don't care too much about yet, some text is selected, and the button is tested.  If it was OK, the
  4157. return value from the second JSR is TSTed and if it was zero (which we are assumming), branch back to
  4158. 1E4FC0 - back to the ModalDialog JSR.  So this route is incorrect.  Going back, we now need to assume
  4159. that the branch at line 1E4FF0 did execute.  This time, we jump right to the button check, skip the
  4160. branch since OK was hit, and again TST the return value from the second JSR.  Since the branch
  4161. executed, this value cannot be zero, so execution proceeds.  Looking down a few lines we note that
  4162. there does not seem to be any more branches back to the ModalDialog JSR so we can tentatively assume
  4163. that this is the end of the protection.
  4164.  
  4165. To apply the crack immediately, just make sure that branch executes.  You can do this by typing BRA
  4166. right over the BNE in TMON.  If, however, you want to make a cracked, unserialized copy (which you
  4167. can then serialize with anything you like) you need to figure out where code will be in Resedit and
  4168. change that BNE to BRA.  Unlike the listings I have pasted into this document, TMON will tell you
  4169. exactly where the code is in the file.  Refer to the above section on TMON MacNosy and Resedit for
  4170. details, but essentially just find the Code Resource ID # and the offset from the TMON listing.  Then
  4171. Exit TMON and let Infini-d cancel out.  Next open it the proper code resource in Resedit, scan down
  4172. to the proper offset, and find the BNE (which is 66 in hex) and change it to BRA (60 in hex).  Save
  4173. changes and you are set.
  4174.  
  4175. FrameMaker 3.0
  4176.  
  4177. Serial number dialog scheme again.  This one, however, presents a slight variation - Nosy won't
  4178. disassemble it properly.  This means that you will have to do all your cracking from within TMON.
  4179.  
  4180. Step 1:  Where to start looking.
  4181.  
  4182. The only choice we have is to break in via TMON.  The simplest way to do this is to drop into TMON,
  4183. set a Trace Interrupt for ModalDialog and Exit.  Now launch Framemaker 3.0 and wait for TMON to break
  4184. in  Here is the code you would see: (note that this listing is from TMON Pro - a TMON 2.8.x listing
  4185. will be slightly different)
  4186.  
  4187. 005B4F88:'CODE'Æ$0003ü$040C+$0284 PEA      $01AA(A5)
  4188. 005B4F8C:'CODE'Æ$0003ü$040C+$0288 PEA      `FDEC(A6)
  4189. 005B4F90:P 'CODE'Æ$0003ü$040C+$2ä _ModalDialog
  4190. 005B4F92:'CODE'Æ$0003ü$040C+$028E MOVE.W  `FDEC(A6),D0
  4191. 005B4F96:'CODE'Æ$0003ü$040C+$0292 EXT.L      D0
  4192. 005B4F98:'CODE'Æ$0003ü$040C+$0294 MOVEQ      #$01,D1
  4193. 005B4F9A:'CODE'Æ$0003ü$040C+$0296 CMP.L      D0,D1
  4194. 005B4F9C:'CODE'Æ$0003ü$040C+$0298 BNE      ^$005B50EA                ;'CODE'Æ$0003ü$040C+$3E6
  4195. 005B4FA0:* 'CODE'Æ$0003ü$040C+$2ä CLR.W      `FDEC(A6)
  4196. 005B4FA4:'CODE'Æ$0003ü$040C+$02A0 CLR.B      (A3)
  4197. 005B4FA6:'CODE'Æ$0003ü$040C+$02A2 TST.L      `96FA(A5)
  4198. 005B4FAA:'CODE'Æ$0003ü$040C+$02A6 BEQ.S      ^$005B4FC4                ;'CODE'Æ$0003ü$040C+$2C0
  4199. 005B4FAC:'CODE'Æ$0003ü$040C+$02A8 MOVE.L  A4,-(A7)
  4200. 005B4FAE:'CODE'Æ$0003ü$040C+$02AA PEA      $3802                          ;$000037D8+$2A
  4201. 005B4FB2:'CODE'Æ$0003ü$040C+$02AE JSR      $1702(A5)
  4202. 005B4FB6:'CODE'Æ$0003ü$040C+$02B2 MOVE.L  A3,-(A7)
  4203. 005B4FB8:'CODE'Æ$0003ü$040C+$02B4 MOVE.L  A4,-(A7)
  4204. 005B4FBA:'CODE'Æ$0003ü$040C+$02B6 JSR      $419A(A5)
  4205. 005B4FBE:'CODE'Æ$0003ü$040C+$02BA LEA      $0010(A7),A7
  4206. 005B4FC2:'CODE'Æ$0003ü$040C+$02BE BRA.S      ^$005B4FE8                ;'CODE'Æ$0003ü$040C+$2E4
  4207. 005B4FC4:'CODE'Æ$0003ü$040C+$02C0 MOVE.L  `FDE8(A6),-(A7)
  4208. 005B4FC8:'CODE'Æ$0003ü$040C+$02C4 MOVEQ      #$05,D0
  4209. 005B4FCA:'CODE'Æ$0003ü$040C+$02C6 MOVE.W  D0,-(A7)
  4210. 005B4FCC:'CODE'Æ$0003ü$040C+$02C8 PEA      `FDEE(A6)
  4211. 005B4FD0:'CODE'Æ$0003ü$040C+$02CC PEA      `FDF0(A6)
  4212. 005B4FD4:'CODE'Æ$0003ü$040C+$02D0 PEA      `FDF4(A6)
  4213. 005B4FD8:'CODE'Æ$0003ü$040C+$02D4 _GetDItem
  4214. 005B4FDA:'CODE'Æ$0003ü$040C+$02D6 TST.L      `FDF0(A6)
  4215. 005B4FDE:'CODE'Æ$0003ü$040C+$02DA BEQ.S      ^$005B4FE8                ;'CODE'Æ$0003ü$040C+$2E4
  4216. 005B4FE0:'CODE'Æ$0003ü$040C+$02DC MOVE.L  `FDF0(A6),-(A7)
  4217. 005B4FE4:'CODE'Æ$0003ü$040C+$02E0 MOVE.L  A3,-(A7)
  4218. 005B4FE6:'CODE'Æ$0003ü$040C+$02E2 _GetIText
  4219. 005B4FE8:'CODE'Æ$0003ü$040C+$02E4 MOVE.L  A3,-(A7)
  4220. 005B4FEA:'CODE'Æ$0003ü$040C+$02E6 JSR      ^$005B5670                ;'CODE'Æ$0003ü$040C+$96C
  4221. 005B4FEE:'CODE'Æ$0003ü$040C+$02EA TST.L      D0
  4222. 005B4FF0:'CODE'Æ$0003ü$040C+$02EC ADDQ.L  #4,A7
  4223. 005B4FF2:'CODE'Æ$0003ü$040C+$02EE BMI      ^$005B50C8                ;'CODE'Æ$0003ü$040C+$3C4
  4224. 005B4FF6:'CODE'Æ$0003ü$040C+$02F2 CMPI.L  #$00000005,D0
  4225. 005B4FFC:'CODE'Æ$0003ü$040C+$02F8 BGT      ^$005B50C8                ;'CODE'Æ$0003ü$040C+$3C4
  4226. 005B5000:'CODE'Æ$0003ü$040C+$02FC ADD.L      D0,D0
  4227. 005B5002:'CODE'Æ$0003ü$040C+$02FE MOVE.W  ^$005B500A(D0.L),D0            ;'CODE'Æ$0003ü$040C+$306
  4228. 005B5006:'CODE'Æ$0003ü$040C+$0302 JMP      ^$005B5008(D0.W)            ;'CODE'Æ$0003ü$040C+$304
  4229.  
  4230.  
  4231. If you try to step through this and enter your name etc., you will find that ModalDialog is exiting
  4232. after any keystroke.  The way to get around this hassle is to get rid of the Trace Interrupt and set
  4233. a breakpoint after the OK button is hit.  How you ask?  Well, take a look at the code that follows
  4234. the ModalDialog.  First, D0 gets the dialog item that was modified.  Next D1 gets the value 1 and the
  4235. two are compared.  From Resedit, you can find the dialog item numbers for all the items and it turns
  4236. out that item 1 is the OK button, and item 5 is the serial number - these are the two important ones
  4237. since the program can't proceed until the OK button is hit (we don't care about the cancel button
  4238. being hit) and then the program must check the serial number.  Following the compare, we note that if
  4239. they are not equal (i.e. OK button not hit) then it goes off somewhere.  The next instruction must be
  4240. the one that executes after the user hits the OK button.  So set your breakpoint at the line that
  4241. reads CLR.W  FDEC(A6) which is at address 5B4FA0 (this will vary) - and in fact you can see the
  4242. asterisk in the listing denoting that I have done just that.  Now exit, enter your name and company
  4243. and serial number (keep typing anything until the OK button lights up) and hit OK.  Now TMON breaks
  4244. in again at the breakpoint.  Now we can begin the crack.
  4245.  
  4246. Determining how to implement the crack.
  4247.  
  4248. Before you continue, think about what the program must do at this point if it wants to validate your
  4249. serial number (here it helps to have read Inside Mac on dialogs).  First the program must obtain a
  4250. pointer to the dialog item #5 (the serial number field) and then it must obtain a pointer to the text
  4251. contained in that item.  Knowing this, you can just scan down until you see a GetDItem trap followed
  4252. closely by a GetIText trap.  After this last trap, the program can do its validation.  Here is that
  4253. piece of code:
  4254.  
  4255. MOVE.L  A3,-(A7)
  4256. _GetIText
  4257. MOVE.L  A3,-(A7)
  4258. JSR      ^$005B5670        
  4259. TST.L      D0
  4260. ADDQ.L  #4,A7
  4261. BMI      ^$005B50C8        
  4262. CMPI.L  #$00000005,D0
  4263. BGT      ^$005B50C8        
  4264. ADD.L      D0,D0
  4265. MOVE.W  ^$005B500A(D0.L),D0    
  4266. JMP      ^$005B5008(D0.W)    
  4267.  
  4268. We can note that A3 is the pointer that will point to the text after the trap.  Once A3 has the text,
  4269. a subroutine is called and D0 is tested.  At this point, we cannot be sure whether the branch
  4270. executes if the serial passed or failed, so we had better take a quick look at the code at address
  4271. 5B50C8.  I am not going to show it here, but that code does some crap then calles ParamText and then
  4272. a Dialog call so it is probably safe to guess that the branch above jumps to the error code. 
  4273.  
  4274. With this assumption in mind, what can we do about it?  An initial guess would be to just make that
  4275. BMI either not execute or even better, make the BMI branch down to the ADD.L D0,D0.  Unfortunately,
  4276. if you look at the last two lines, you can see that D0 not only determines whether the code branches
  4277. to the error routine, but is then used for a JMP instruction so we had better take care of D0.  Let's
  4278. take a quick look at that JSR up a few lines that sets D0 in the first place and remember, we are
  4279. trying to figure out what D0 should be set to.  Also remember that the branch is a BMI meaning that
  4280. the error occurs if the high bit of D0 is set.
  4281.  
  4282. 004B1508:'CODE'Æ$0003ü$04C8+$096C LINK.W  A6,#$FF00
  4283. 004B150C:'CODE'Æ$0003ü$04C8+$0970 MOVEM.L A3/A4,-(A7)
  4284. 004B1510:'CODE'Æ$0003ü$04C8+$0974 LEA      `FF00(A6),A4
  4285. 004B1514:'CODE'Æ$0003ü$04C8+$0978 MOVEA.L $0008(A6),A3
  4286. 004B1518:'CODE'Æ$0003ü$04C8+$097C MOVEQ      #$00,D0
  4287. 004B151A:'CODE'Æ$0003ü$04C8+$097E MOVE.B  (A3),D0
  4288. 004B151C:'CODE'Æ$0003ü$04C8+$0980 MOVEQ      #$06,D1
  4289. 004B151E:'CODE'Æ$0003ü$04C8+$0982 CMP.L      D0,D1
  4290. 004B1520:'CODE'Æ$0003ü$04C8+$0984 BLE.S      ^$004B1526                ;'CODE'Æ$0003ü$04C8+$98A
  4291. 004B1522:'CODE'Æ$0003ü$04C8+$0986 MOVEQ      #`FF,D0
  4292. 004B1524:'CODE'Æ$0003ü$04C8+$0988 BRA.S      ^$004B1592                ;'CODE'Æ$0003ü$04C8+$9F6
  4293. 004B1526:'CODE'Æ$0003ü$04C8+$098A MOVEQ      #$00,D0
  4294. 004B1528:'CODE'Æ$0003ü$04C8+$098C MOVE.B  (A3),D0
  4295. 004B152A:'CODE'Æ$0003ü$04C8+$098E MOVEQ      #$28,D1                        ;'('
  4296. 004B152C:'CODE'Æ$0003ü$04C8+$0990 CMP.L      D0,D1
  4297. 004B152E:'CODE'Æ$0003ü$04C8+$0992 BGE.S      ^$004B1534                ;'CODE'Æ$0003ü$04C8+$998
  4298. 004B1530:'CODE'Æ$0003ü$04C8+$0994 MOVEQ      #`FF,D0
  4299. 004B1532:'CODE'Æ$0003ü$04C8+$0996 BRA.S      ^$004B1592                ;'CODE'Æ$0003ü$04C8+$9F6
  4300. 004B1534:'CODE'Æ$0003ü$04C8+$0998 MOVE.L  A4,-(A7)
  4301. 004B1536:'CODE'Æ$0003ü$04C8+$099A PEA      $3802                          ;$000037D8+$2A
  4302. 004B153A:'CODE'Æ$0003ü$04C8+$099E JSR      $1702(A5)
  4303. 004B153E:'CODE'Æ$0003ü$04C8+$09A2 MOVE.L  A4,-(A7)
  4304. 004B1540:'CODE'Æ$0003ü$04C8+$09A4 JSR      $0532(A5)
  4305. 004B1544:'CODE'Æ$0003ü$04C8+$09A8 MOVE.L  A3,-(A7)
  4306. 004B1546:'CODE'Æ$0003ü$04C8+$09AA MOVE.L  A4,-(A7)
  4307. 004B1548:'CODE'Æ$0003ü$04C8+$09AC JSR      $0392(A5)
  4308. 004B154C:'CODE'Æ$0003ü$04C8+$09B0 TST.L      D0
  4309. 004B154E:'CODE'Æ$0003ü$04C8+$09B2 LEA      $0014(A7),A7
  4310. 004B1552:'CODE'Æ$0003ü$04C8+$09B6 BEQ.S      ^$004B1558                ;'CODE'Æ$0003ü$04C8+$9BC
  4311. 004B1554:'CODE'Æ$0003ü$04C8+$09B8 MOVEQ      #$05,D0
  4312. 004B1556:'CODE'Æ$0003ü$04C8+$09BA BRA.S      ^$004B1592                ;'CODE'Æ$0003ü$04C8+$9F6
  4313. 004B1558:'CODE'Æ$0003ü$04C8+$09BC MOVE.B  $0001(A3),D0
  4314. 004B155C:'CODE'Æ$0003ü$04C8+$09C0 SUBI.B  #$30,D0
  4315. 004B1560:'CODE'Æ$0003ü$04C8+$09C4 BCS.S      ^$004B1590                ;'CODE'Æ$0003ü$04C8+$9F4
  4316. 004B1562:'CODE'Æ$0003ü$04C8+$09C6 CMPI.B  #$02,D0
  4317. 004B1566:'CODE'Æ$0003ü$04C8+$09CA BHI.S      ^$004B1590                ;'CODE'Æ$0003ü$04C8+$9F4
  4318. 004B1568:'CODE'Æ$0003ü$04C8+$09CC MOVEQ      #$00,D1
  4319. 004B156A:'CODE'Æ$0003ü$04C8+$09CE MOVE.B  D0,D1
  4320. 004B156C:'CODE'Æ$0003ü$04C8+$09D0 ADD.W      D1,D1
  4321. 004B156E:'CODE'Æ$0003ü$04C8+$09D2 MOVE.W  ^$004B1576(D1.W),D1            ;'CODE'Æ$0003ü$04C8+$9DA
  4322. 004B1572:'CODE'Æ$0003ü$04C8+$09D6 JMP      ^$004B1574(D1.W)            ;'CODE'Æ$0003ü$04C8+$9D8
  4323.  
  4324. There are no traps here to quickly tell us what is happening, but we can quickly look at the lines
  4325. that affect D0.  Basically, there are a bunch of interspersed MOVEQ instructions putting various
  4326. values into D0.  One of the values is $FF which (since the high bit of $FF is set - in fact, all the
  4327. bits of $FF are set) must trigger the error in the previous procedure.  Other values include 5 and 0. 
  4328. Right now, that is enough information to proceed with the previous procedure - if we need more in
  4329. depth info, we can always come back.  So we have the following code again:
  4330.  
  4331. MOVE.L  A3,-(A7)
  4332. JSR      ^$005B5670        
  4333. TST.L      D0
  4334. ADDQ.L  #4,A7
  4335. BMI      ^$005B50C8        
  4336. CMPI.L  #$00000005,D0
  4337. BGT      ^$005B50C8        
  4338. ADD.L      D0,D0
  4339. MOVE.W  ^$005B500A(D0.L),D0    
  4340. JMP      ^$005B5008(D0.W)    
  4341.  
  4342. Once again, we have an initial BMI which tells us that $FF won't work for D0.  We also have BGT after
  4343. comparing D0 with 5 which branches to the error - so D0 must be between 0 and 5 (the other values we
  4344. noted from the subroutine above).  At this point, I would (and did) simply try inserting values into
  4345. D0.  I started with 5 and the program went into Demo mode - strike one.  Next I tried 1 and some
  4346. other error occured.  Finally, I tried 0 and the program continued flawlessly.
  4347.  
  4348. So you are asking, how exactly might you go about inserting these values into D0?  Consider: once D0
  4349. is set to the proper value, the two branches become meaningless since they would not execute anyways
  4350. (they only execute if there is an error).  This little tidbit tells us that we can safely overwrite
  4351. these instructions with anything we like.  So we have several free bytes to put our own code into
  4352. (don't panic yet - this is pretty straightforward) and all our code has to do is set D0 to 0 then
  4353. proceed.  One quick note:  Never Never Ever modify code that affects the stack.  If you do, you can
  4354. easily cause system errors later on down the road.  In the above code, this translates into not
  4355. changing the ADDQ.L  #4,A7 (A7 is the stack pointer, remember?).  So what is the easiest way to put 0
  4356. into D0?  Use a MOVEQ instruction.  This is particularly nice because you probably do not know the
  4357. machine hex code for instructions (like me).  But that subroutine we looked at before is chalk full
  4358. of MOVEQ instructions.  If you look, a MOVEQ 0 #0,D0 translates into 70 00.  So far so good except
  4359. that the stupid BMI is one of those 4 byte branches.  So we still have two bytes left that will be
  4360. garbage since we just changed the first two.  This is an excellent candidate for a NOP instruction -
  4361. a two byte instruction that does absolutely nothing.  The code for this (from the Cracker's Guide
  4362. Part 1) is 4E 71.
  4363.  
  4364. So, open a dump window to the PC and find the BMI (I think it is 68 00 00 D4 or something like that). 
  4365. Change the four values to 70 00 4E 71 and now the program loads D0 with the correct value and
  4366. proceeds as if nothing had happened.  Now you have the crack, but you want to make a cracked /
  4367. un-serialized copy right?  So, unstuff a fresh copy of the application, open it in Resedit, and open
  4368. the proper CODE resource.  To find the ID #, look back at the TMON listing.  It says CODE 0003 plus
  4369. some benutia about the File reference number and then +nnnn where nnnn is the offset from the
  4370. beginning of the Code resource.  There is all you need.  Open CODE ID 3 and jump down to line 2E8
  4371. (since 2EE is our byte) and change the 68 00 00 D4 to 70 00 4E 71.  Now run it and enter anything you
  4372. like for the serial number.
  4373.  
  4374. QuickFormat 7.01
  4375.  
  4376.     [due to burn-out, the final sections have not been written up]
  4377.  
  4378.      33E:                                 QUAL    CHECKFOR ; b# =508  s#3  =proc196
  4379.  
  4380.                                ;-refs -  3/INITPROG  
  4381.  
  4382.      33E: 4E56 FFE4      'NV..'  CHECKFOR LINK    A6,#-$1C
  4383.      342: 48E7 0108      'H...'           MOVEM.L D7/A4,-(A7)
  4384.      346: 594F           'YO'             SUBQ    #4,A7
  4385.      348: 2F3C 6465 6D6F '/<demo'         PUSH.L  #'demo'
  4386.      34E: 3F3C 0080      '?<..'           PUSH    #128
  4387.      352: A81F           '..'             _Get1Resource ; (theType:ResType; ID:INTEGER):Handle 
  4388.      354: 285F           '(_'             POP.L   A4
  4389.      356: 200C           ' .'             MOVE.L  A4,D0
  4390.      358: 6656           30003B0          BNE.S   lih_2
  4391.      35A: 594F           'YO'             SUBQ    #4,A7
  4392.      35C: 7004           'p.'             MOVEQ   #4,D0
  4393.      35E: 2F00           '/.'             PUSH.L  D0
  4394.      360: 4EAD 0082      10005EA          JSR     NewHandle(A5)
  4395.      364: 285F           '(_'             POP.L   A4
  4396.      366: 2F0C           '/.'             PUSH.L  A4
  4397.      368: 4EAD 0092      1000614          JSR     HLock(A5)
  4398.      36C: 2054           ' T'             MOVEA.L (A4),A0
  4399.      36E: 20BC 000F 423F ' ...B?'         MOVE.L  #$F423F,(A0)
  4400.      374: 2F0C           '/.'             PUSH.L  A4
  4401.      376: 2F3C 6465 6D6F '/<demo'         PUSH.L  #'demo'
  4402.      37C: 3F3C 0080      '?<..'           PUSH    #128
  4403.      380: 487A 007C      30003FE          PEA     data209     ; len= 2
  4404.      384: A9AB           '..'           _AddResource ; (theResource:Handle; theType:ResType;
  4405. theID:INTEGER; name:Str255) 
  4406.      386: 554F           'UO'             SUBQ    #2,A7
  4407.      388: A9AF           '..'             _ResError ; :OSErr 
  4408.      38A: 4A5F           'J_'             TST     (A7)+
  4409.      38C: 6714           30003A2          BEQ.S   lih_1
  4410.      38E: 3F3C 008B      '?<..'           PUSH    #139
  4411.      392: 1F3C 0001      '.<..'           PUSH.B  #1
  4412.      396: 4EAD 0462      2000B7C          JSR     DOSTANDA(A5)
  4413.      39A: 554F           'UO'             SUBQ    #2,A7
  4414.      39C: A9AF           '..'             _ResError ; :OSErr 
  4415.      39E: 4EAD 0452      20009FE          JSR     DOERROR(A5)
  4416.      3A2: 2F0C           '/.'    lih_1    PUSH.L  A4
  4417.      3A4: A9AA           '..'             _ChangedResource ; (theResource:Handle) 
  4418.      3A6: 2F0C           '/.'             PUSH.L  A4
  4419.      3A8: A9B0           '..'             _WriteResource ; (theResource:Handle) 
  4420.      3AA: 2F0C           '/.'             PUSH.L  A4
  4421.      3AC: 4EAD 009A      100061E          JSR     HUnLock(A5)
  4422.      3B0: 2F0C           '/.'    lih_2    PUSH.L  A4
  4423.      3B2: 4EAD 0092      1000614          JSR     HLock(A5)
  4424.      3B6: 2E3C 176F 7C4E '.<.o|N'         MOVE.L  #$176F7C4E,D7
  4425.      3BC: 2054           ' T'             MOVEA.L (A4),A0
  4426.      3BE: BE90           '..'             CMP.L   (A0),D7
  4427.      3C0: 6606           30003C8          BNE.S   lih_3
  4428.      3C2: 422D FDE2        -$21E          CLR.B   glob73(A5)
  4429.      3C6: 6020           30003E8          BRA.S   lih_4
  4430.      3C8: 554F           'UO'    lih_3    SUBQ    #2,A7
  4431.      3CA: 2F07           '/.'             PUSH.L  D7
  4432.      3CC: 4EBA FE68      3000236          JSR     DODEMODI
  4433.      3D0: 1B5F FDE2        -$21E          POP.B   glob73(A5)
  4434.      3D4: 102D FDE2        -$21E          MOVE.B  glob73(A5),D0
  4435.      3D8: 5300           'S.'             SUBQ.B  #1,D0
  4436.      3DA: 670C           30003E8          BEQ.S   lih_4
  4437.      3DC: 2054           ' T'             MOVEA.L (A4),A0
  4438.      3DE: 2087           ' .'             MOVE.L  D7,(A0)
  4439.      3E0: 2F0C           '/.'             PUSH.L  A4
  4440.      3E2: A9AA           '..'             _ChangedResource ; (theResource:Handle) 
  4441.      3E4: 2F0C           '/.'             PUSH.L  A4
  4442.      3E6: A9B0           '..'             _WriteResource ; (theResource:Handle) 
  4443.      3E8: 2F0C           '/.'    lih_4    PUSH.L  A4
  4444.      3EA: 4EAD 009A      100061E          JSR     HUnLock(A5)
  4445.      3EE: 4CDF 1080      'L...'           MOVEM.L (A7)+,D7/A4
  4446.      3F2: 4E5E           'N^'             UNLK    A6
  4447.      3F4: 4E75           'Nu'             RTS     
  4448.  
  4449. Finder 7 Menus
  4450.  
  4451.  
  4452.      458:                                 QUAL    GETPASSW ; b# =31  s#1  =proc14
  4453.  
  4454.                                  vap_1     VEQU  -288
  4455.                                  vap_2     VEQU  -280
  4456.                                  vap_3     VEQU  -276
  4457.                                  vap_4     VEQU  -274
  4458.                                  vap_5     VEQU  -272
  4459.      458:                                 VEND    
  4460.  
  4461.                                ;-refs - DOCOMMAN  
  4462.  
  4463.      458: 4E56 FED8      'NV..'  GETPASSW LINK    A6,#-$128
  4464.      45C: 48E7 0018      'H...'           MOVEM.L A3-A4,-(A7)
  4465.      460: 4A2D FEFE        -$102          TST.B   glob59(A5)
  4466.      464: 670C           1000472          BEQ.S   lap_1
  4467.      466: 487A 01B4      100061C          PEA     data23      ; 'Password has already
  4468.      46A: 4EBA 139E      100180A          JSR     OUTPUTTE
  4469.      46E: 6000 00A2      1000512          BRA     lap_5
  4470.      472: 3F2D FEBA        -$146 lap_1    PUSH    glob28(A5)
  4471.      476: A998           '..'             _UseResFile ; (frefNum:RefNum) 
  4472.      478: 594F           'YO'             SUBQ    #4,A7
  4473.      47A: 3F3C 0101      '?<..'           PUSH    #257
  4474.      47E: 42A7           'B.'             CLR.L   -(A7)
  4475.      480: 70FF           'p.'             MOVEQ   #-1,D0
  4476.      482: 2F00           '/.'             PUSH.L  D0
  4477.      484: A97C           '.|'             _GetNewDialog ; (DlgID:INTEGER; wStorage:Ptr;
  4478. behind:WindowPtr):DialogPtr 
  4479.      486: 285F           '(_'             POP.L   A4
  4480.      488: 2F0C           '/.'             PUSH.L  A4
  4481.      48A: 3F3C 0002      '?<..'           PUSH    #2
  4482.      48E: 486E FEEC      200FEEC          PEA     vap_3(A6)
  4483.      492: 486E FEE8      200FEE8          PEA     vap_2(A6)
  4484.      496: 486E FEE0      200FEE0          PEA     vap_1(A6)
  4485.      49A: A98D           '..'           GetDItem ; (dlg:DialogPtr; itemNo:INTEGER; VAR kind:INTEGER;
  4486. VAR item:Handle; VAR box:Rect) 
  4487.      49C: 42A7           'B.'    lap_2    CLR.L   -(A7)
  4488.      49E: 486E FEEE      200FEEE          PEA     vap_4(A6)
  4489.      4A2: A991           '..'             _ModalDialog ; (filterProc:ProcPtr; VAR itemHit:INTEGER) 
  4490.      4A4: 0C6E 0001 FEEE 200FEEE          CMPI    #1,vap_4(A6)
  4491.      4AA: 66F0           100049C          BNE     lap_2
  4492.      4AC: 2F2E FEE8      200FEE8          PUSH.L  vap_2(A6)
  4493.      4B0: 486E FEF0      200FEF0          PEA     vap_5(A6)
  4494.      4B4: A990           '..'             _GetIText ; (item:Handle; VAR text:Str255) 
  4495.      4B6: 487A 0152      100060A          PEA     data22      ; 'cc5187efH28b911af'
  4496.      4BA: 486E FEF0      200FEF0          PEA     vap_5(A6)
  4497.      4BE: 4EBA FC4A      100010A          JSR     proc6
  4498.      4C2: 6642           1000506          BNE.S   lap_3
  4499.      4C4: 594F           'YO'             SUBQ    #4,A7
  4500.      4C6: 486E FEF0      200FEF0          PEA     vap_5(A6)
  4501.      4CA: A906           '..'             _NewString ; (theString:Str255):StringHandle 
  4502.      4CC: 265F           '&_'             POP.L   A3
  4503.      4CE: 2F0B           '/.'             PUSH.L  A3
  4504.      4D0: 2F3C 5354 5220 '/<STR '         PUSH.L  #'STR '
  4505.      4D6: 3F3C 0080      '?<..'           PUSH    #128
  4506.      4DA: 487A 012C      1000608          PEA     data21      ; len= 2
  4507.      4DE: A9AB           '..'             _AddResource ; (theResource:Handle; theType:ResType;
  4508. theID:INTEGER; name:Str255) 
  4509.      4E0: 3F2D FEBA        -$146          PUSH    glob28(A5)
  4510.      4E4: A999           '..'             _UpdateResFile ; (frefNum:RefNum) 
  4511.      4E6: 1B7C 0001 FEFE   -$102          MOVE.B  #1,glob59(A5)
  4512.      4EC: 487A 00C0      10005AE          PEA     data20      ; 'Thanks for registeri
  4513.      4F0: 4EBA 1318      100180A          JSR     OUTPUTTE
  4514.      4F4: 4A2D FEFE        -$102          TST.B   glob59(A5)
  4515.      4F8: 6714           100050E          BEQ.S   lap_4
  4516.      4FA: 2F2D FEB0        -$150          PUSH.L  glob25(A5)
  4517.      4FE: 487A 0086      1000586          PEA     data19      ; ''Thank you for payin
  4518.      502: A91A           '..'             _SetWTitle ; (theWindow:WindowPtr; title:Str255) 
  4519.      504: 6008           100050E          BRA.S   lap_4
  4520.      506: 487A 001A      1000522 lap_3    PEA     data18      ; 'For only $10, you ca
  4521.      50A: 4EBA 12FE      100180A          JSR     OUTPUTTE
  4522.      50E: 2F0C           '/.'    lap_4    PUSH.L  A4
  4523.      510: A982           '..'             _CloseDialog ; (dlg:DialogPtr) 
  4524.      512: 4CDF 1800      'L...'  lap_5    MOVEM.L (A7)+,A3-A4
  4525.      516: 4E5E           'N^'             UNLK    A6
  4526.      518: 4E75           'Nu'             RTS     
  4527. ======================================================================
  4528. If I swiped any Kracks or dialog from you, thanks for contributing.
  4529. ======================================================================
  4530.